move v.v to cmd/v
parent
3f5e4c55b2
commit
9332a83ce6
|
@ -12,8 +12,8 @@ jobs:
|
||||||
echo "Changed files compared to origin/master are:" && git diff --name-status origin/master HEAD -- '*.v'
|
echo "Changed files compared to origin/master are:" && git diff --name-status origin/master HEAD -- '*.v'
|
||||||
- name: Build v (there is no need for dependencies for fmt)
|
- name: Build v (there is no need for dependencies for fmt)
|
||||||
run: make -j4
|
run: make -j4
|
||||||
- name: Build a production tools/vfmt
|
- name: Build a production cmd/tools/vfmt
|
||||||
run: ./v -prod -d vfmt tools/vfmt.v
|
run: ./v -prod -d vfmt cmd/tools/vfmt.v
|
||||||
- name: Run v fmt -diff on only the changed files. Does NOT fail for now.
|
- name: Run v fmt -diff on only the changed files. Does NOT fail for now.
|
||||||
run: git diff --name-status origin/master HEAD -- '*.v' |grep -v '^D'|rev|cut -f1|rev| xargs ./v fmt -noerror -diff
|
run: git diff --name-status origin/master HEAD -- '*.v' |grep -v '^D'|rev|cut -f1|rev| xargs ./v fmt -noerror -diff
|
||||||
- name: Run v test-fmt
|
- name: Run v test-fmt
|
||||||
|
@ -28,12 +28,12 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y libglfw3 libglfw3-dev libfreetype6-dev libssl-dev sqlite3 libsqlite3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y libglfw3 libglfw3-dev libfreetype6-dev libssl-dev sqlite3 libsqlite3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
||||||
- name: Build v
|
- name: Build v
|
||||||
run: echo $VFLAGS && make -j4 && ./v -cg -o v v.v
|
run: echo $VFLAGS && make -j4 && ./v -cg -o v cmd/v
|
||||||
- name: Test v->c
|
- name: Test v->c
|
||||||
run: |
|
run: |
|
||||||
sudo ln -s /var/tmp/tcc/bin/tcc /usr/local/bin/tcc
|
sudo ln -s /var/tmp/tcc/bin/tcc /usr/local/bin/tcc
|
||||||
tcc -version
|
tcc -version
|
||||||
./v -o v2 v.v # Make sure vtcc can build itself
|
./v -o v2 cmd/v # Make sure vtcc can build itself
|
||||||
./v -silent test-compiler
|
./v -silent test-compiler
|
||||||
- name: Test v binaries
|
- name: Test v binaries
|
||||||
run: ./v -silent build-vbinaries
|
run: ./v -silent build-vbinaries
|
||||||
|
@ -71,9 +71,9 @@ jobs:
|
||||||
brew install freetype glfw openssl postgres sdl2 sdl2_ttf sdl2_mixer sdl2_image
|
brew install freetype glfw openssl postgres sdl2 sdl2_ttf sdl2_mixer sdl2_image
|
||||||
export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/opt/openssl/lib/"
|
export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/opt/openssl/lib/"
|
||||||
- name: Build V
|
- name: Build V
|
||||||
run: make -j4 && ./v -cg -o v v.v
|
run: make -j4 && ./v -cg -o v cmd/v
|
||||||
- name: Build V using V
|
- name: Build V using V
|
||||||
run: ./v -o v2 v.v && ./v2 -o v3 v.v
|
run: ./v -o v2 cmd/v && ./v2 -o v3 cmd/v
|
||||||
- name: Test symlink
|
- name: Test symlink
|
||||||
run: sudo ./v symlink
|
run: sudo ./v symlink
|
||||||
- name: Set up pg database
|
- name: Set up pg database
|
||||||
|
@ -89,7 +89,7 @@ jobs:
|
||||||
# - name: Test v->js
|
# - name: Test v->js
|
||||||
# run: ./v -o hi.js examples/hello_v_js.v && node hi.js
|
# run: ./v -o hi.js examples/hello_v_js.v && node hi.js
|
||||||
- name: Test symlink
|
- name: Test symlink
|
||||||
run: ./v symlink && v -o v2 v.v
|
run: ./v symlink && v -o v2 cmd/v
|
||||||
- name: Test vsh
|
- name: Test vsh
|
||||||
run: ./v examples/v_script.vsh
|
run: ./v examples/v_script.vsh
|
||||||
- name: Test vid
|
- name: Test vid
|
||||||
|
@ -107,7 +107,7 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y postgresql libpq-dev libglfw3 libglfw3-dev libfreetype6-dev libssl-dev sqlite3 libsqlite3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y postgresql libpq-dev libglfw3 libglfw3-dev libfreetype6-dev libssl-dev sqlite3 libsqlite3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
||||||
- name: Build V
|
- name: Build V
|
||||||
run: make -j4 && ./v -cc gcc -o v v.v
|
run: make -j4 && ./v -cc gcc -o v cmd/v
|
||||||
- name: Test V
|
- name: Test V
|
||||||
run: ./v -silent test-compiler
|
run: ./v -silent test-compiler
|
||||||
- name: Test v binaries
|
- name: Test v binaries
|
||||||
|
@ -122,13 +122,13 @@ jobs:
|
||||||
run: ./v -freestanding -o bare vlib/os/bare/bare_example_linux.v
|
run: ./v -freestanding -o bare vlib/os/bare/bare_example_linux.v
|
||||||
- name: x64 machine code generation
|
- name: x64 machine code generation
|
||||||
run: |
|
run: |
|
||||||
./v -o vprod -prod v.v
|
./v -o vprod -prod cmd/v
|
||||||
cd tools
|
cd cmd/tools
|
||||||
echo "Generating a 1m line V file..."
|
echo "Generating a 1m line V file..."
|
||||||
../vprod gen1m.v
|
../../vprod gen1m.v
|
||||||
./gen1m > 1m.v
|
./gen1m > 1m.v
|
||||||
echo "Building it..."
|
echo "Building it..."
|
||||||
../vprod -x64 -o 1m 1m.v
|
../../vprod -x64 -o 1m 1m.v
|
||||||
echo "Running it..."
|
echo "Running it..."
|
||||||
ls
|
ls
|
||||||
# ./1m
|
# ./1m
|
||||||
|
@ -191,7 +191,7 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y musl musl-tools libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y musl musl-tools libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
||||||
- name: Build v
|
- name: Build v
|
||||||
run: echo $VFLAGS && make -j4 && ./v -cg -o v v.v
|
run: echo $VFLAGS && make -j4 && ./v -cg -o v cmd/v
|
||||||
- name: Test v binaries
|
- name: Test v binaries
|
||||||
run: ./v -silent build-vbinaries
|
run: ./v -silent build-vbinaries
|
||||||
# - name: Test v->js
|
# - name: Test v->js
|
||||||
|
|
|
@ -19,12 +19,12 @@ jobs:
|
||||||
sudo apt-get install --quiet -y sqlite3 libsqlite3-dev
|
sudo apt-get install --quiet -y sqlite3 libsqlite3-dev
|
||||||
sudo apt-get install --quiet -y libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
sudo apt-get install --quiet -y libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
||||||
- name: Build v
|
- name: Build v
|
||||||
run: echo $VFLAGS && make -j4 && ./v -cg -o v v.v
|
run: echo $VFLAGS && make -j4 && ./v -cg -o v cmd/v
|
||||||
- name: Test v->c
|
- name: Test v->c
|
||||||
run: |
|
run: |
|
||||||
sudo ln -s /var/tmp/tcc/bin/tcc /usr/local/bin/tcc
|
sudo ln -s /var/tmp/tcc/bin/tcc /usr/local/bin/tcc
|
||||||
tcc -version
|
tcc -version
|
||||||
./v -o v2 v.v # Make sure vtcc can build itself
|
./v -o v2 cmd/v # Make sure vtcc can build itself
|
||||||
- name: Run network tests
|
- name: Run network tests
|
||||||
run: ./v -d network test vlib/
|
run: ./v -d network test vlib/
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,20 @@ fns.txt
|
||||||
/v.c
|
/v.c
|
||||||
/v.*.c
|
/v.*.c
|
||||||
/v.c.out
|
/v.c.out
|
||||||
/tools/performance_compare
|
/cmd/tools/performance_compare
|
||||||
/tools/oldv
|
/cmd/tools/oldv
|
||||||
/tools/vrepl
|
/cmd/tools/vrepl
|
||||||
/tools/vtest
|
/cmd/tools/vtest
|
||||||
/tools/vtest-compiler
|
/cmd/tools/vtest-compiler
|
||||||
/tools/vtest-fmt
|
/cmd/tools/vtest-fmt
|
||||||
/tools/vfmt
|
/cmd/tools/vfmt
|
||||||
/tools/vbin2v
|
/cmd/tools/vbin2v
|
||||||
/tools/vup
|
/cmd/tools/vup
|
||||||
/tools/vpm
|
/cmd/tools/vpm
|
||||||
/tools/vcreate
|
/cmd/tools/vcreate
|
||||||
/tools/vbuild-examples
|
/cmd/tools/vbuild-examples
|
||||||
/tools/vbuild-tools
|
/cmd/tools/vbuild-tools
|
||||||
/tools/vbuild-vbinaries
|
/cmd/tools/vbuild-vbinaries
|
||||||
/v_g
|
/v_g
|
||||||
/v_cg
|
/v_cg
|
||||||
/v_prod
|
/v_prod
|
||||||
|
|
|
@ -3,7 +3,7 @@ FROM mstorsjo/llvm-mingw
|
||||||
LABEL maintainer="Vitaly Takmazov <vitalyster@gmail.com>"
|
LABEL maintainer="Vitaly Takmazov <vitalyster@gmail.com>"
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN make
|
RUN make
|
||||||
RUN ./v -os windows -o v.c v.v
|
RUN ./v -os windows -o v.c cmd/v
|
||||||
RUN x86_64-w64-mingw32-gcc v.c -std=c99 -w -municode -o v.exe
|
RUN x86_64-w64-mingw32-gcc v.c -std=c99 -w -municode -o v.exe
|
||||||
RUN file v.exe
|
RUN file v.exe
|
||||||
|
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -42,8 +42,8 @@ endif
|
||||||
all: latest_vc latest_tcc
|
all: latest_vc latest_tcc
|
||||||
ifdef WIN32
|
ifdef WIN32
|
||||||
$(CC) $(CFLAGS) -std=c99 -municode -w -o v2.exe $(TMPVC)/$(VCFILE) $(LDFLAGS)
|
$(CC) $(CFLAGS) -std=c99 -municode -w -o v2.exe $(TMPVC)/$(VCFILE) $(LDFLAGS)
|
||||||
./v2.exe -o v3.exe v.v
|
./v2.exe -o v3.exe cmd/v
|
||||||
./v3.exe -o v.exe -prod v.v
|
./v3.exe -o v.exe -prod cmd/v
|
||||||
rm -f v2.exe v3.exe
|
rm -f v2.exe v3.exe
|
||||||
else
|
else
|
||||||
$(CC) $(CFLAGS) -std=gnu11 -w -o v $(TMPVC)/$(VCFILE) $(LDFLAGS) -lm
|
$(CC) $(CFLAGS) -std=gnu11 -w -o v $(TMPVC)/$(VCFILE) $(LDFLAGS) -lm
|
||||||
|
@ -92,10 +92,10 @@ $(TMPVC)/.git/config:
|
||||||
$(MAKE) fresh_vc
|
$(MAKE) fresh_vc
|
||||||
|
|
||||||
selfcompile:
|
selfcompile:
|
||||||
./v -cg -o v v.v
|
./v -cg -o v cmd/v
|
||||||
|
|
||||||
selfcompile-static:
|
selfcompile-static:
|
||||||
./v -cg -cflags '--static' -o v-static v.v
|
./v -cg -cflags '--static' -o v-static cmd/v
|
||||||
|
|
||||||
modules: module_builtin module_strings module_strconv
|
modules: module_builtin module_strings module_strconv
|
||||||
module_builtin:
|
module_builtin:
|
||||||
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
fn main() {
|
fn main() {
|
||||||
exe := os.executable()
|
exe := os.executable()
|
||||||
dir := filepath.dir(exe)
|
dir := filepath.dir(exe)
|
||||||
vdir := filepath.dir(filepath.dir(dir))
|
vdir := filepath.dir(filepath.dir(filepath.dir(dir)))
|
||||||
if !os.exists('$vdir/v') && !os.is_dir('$vdir/vlib') {
|
if !os.exists('$vdir/v') && !os.is_dir('$vdir/vlib') {
|
||||||
println('fast.html generator needs to be located in `v/tools/fast/`')
|
println('fast.html generator needs to be located in `v/cmd/tools/fast`')
|
||||||
}
|
}
|
||||||
println('fast.html generator\n')
|
println('fast.html generator\n')
|
||||||
// Fetch the last commit's hash
|
// Fetch the last commit's hash
|
||||||
|
@ -36,11 +36,11 @@ fn main() {
|
||||||
}
|
}
|
||||||
// Build an optimized V
|
// Build an optimized V
|
||||||
println('Building vprod...')
|
println('Building vprod...')
|
||||||
exec('v -o $vdir/vprod -prod $vdir/v.v')
|
exec('v -o $vdir/vprod -prod $vdir/cmd/v')
|
||||||
println('Measuring...')
|
println('Measuring...')
|
||||||
diff1 := measure('$vdir/vprod -cc clang -o v.c $vdir/v.v')
|
diff1 := measure('$vdir/vprod -cc clang -o v.c $vdir/cmd/v')
|
||||||
diff2 := measure('$vdir/vprod -cc clang -o v2 $vdir/v.v')
|
diff2 := measure('$vdir/vprod -cc clang -o v2 $vdir/cmd/v')
|
||||||
diff3 := measure('$vdir/vprod -x64 $vdir/tools/1mil.v')
|
diff3 := measure('$vdir/vprod -x64 $vdir/cmd/tools/1mil.v')
|
||||||
diff4 := measure('$vdir/vprod -cc clang $vdir/examples/hello_world.v')
|
diff4 := measure('$vdir/vprod -cc clang $vdir/examples/hello_world.v')
|
||||||
//println('Building V took ${diff}ms')
|
//println('Building V took ${diff}ms')
|
||||||
commit_date := exec('git log -n1 --pretty="format:%at"')
|
commit_date := exec('git log -n1 --pretty="format:%at"')
|
|
@ -38,7 +38,7 @@ td {
|
||||||
<h2>Is V still fast?</h2>
|
<h2>Is V still fast?</h2>
|
||||||
|
|
||||||
Monitoring compilation speed for each commit. <br><br>
|
Monitoring compilation speed for each commit. <br><br>
|
||||||
Source code: <a target=blank href='https://github.com/vlang/v/blob/master/tools/fast/fast.v'>fast.v</a> <br><br>
|
Source code: <a target=blank href='https://github.com/vlang/v/blob/master/cmd/tools/fast/fast.v'>fast.v</a> <br><br>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
|
@ -291,7 +291,7 @@ fn (gen_vc mut GenVC) generate() {
|
||||||
v_flags := if os_name == 'nix' { '-output-cross-platform-c' } else { '-os $os_name' }
|
v_flags := if os_name == 'nix' { '-output-cross-platform-c' } else { '-os $os_name' }
|
||||||
c_file := 'v${vc_suffix}.c'
|
c_file := 'v${vc_suffix}.c'
|
||||||
// try generate .c file
|
// try generate .c file
|
||||||
gen_vc.cmd_exec('$v_exec $v_flags -o $c_file $git_repo_dir_v/v.v')
|
gen_vc.cmd_exec('$v_exec $v_flags -o $c_file $git_repo_dir_v/cmd/v')
|
||||||
// check if the c file seems ok
|
// check if the c file seems ok
|
||||||
gen_vc.assert_file_exists_and_is_not_too_short(c_file, err_msg_gen_c)
|
gen_vc.assert_file_exists_and_is_not_too_short(c_file, err_msg_gen_c)
|
||||||
// embed the latest v commit hash into the c file
|
// embed the latest v commit hash into the c file
|
|
@ -39,7 +39,7 @@ pub fn new_test_session(vargs string) TestSession {
|
||||||
pub fn vexe_path() string {
|
pub fn vexe_path() string {
|
||||||
// NB: tools extracted from v require that the VEXE
|
// NB: tools extracted from v require that the VEXE
|
||||||
// environment variable contains the path to the v executable location.
|
// environment variable contains the path to the v executable location.
|
||||||
// They are usually launched by vlib/compiler/vtools.v,
|
// They are usually launched by cmd/v/simple_tool.v,
|
||||||
// launch_tool/1 , which provides it.
|
// launch_tool/1 , which provides it.
|
||||||
return os.getenv('VEXE')
|
return os.getenv('VEXE')
|
||||||
}
|
}
|
||||||
|
@ -238,11 +238,11 @@ pub fn building_any_v_binaries_failed() bool {
|
||||||
testing.vlib_should_be_present(parent_dir)
|
testing.vlib_should_be_present(parent_dir)
|
||||||
os.chdir(parent_dir)
|
os.chdir(parent_dir)
|
||||||
mut failed := false
|
mut failed := false
|
||||||
v_build_commands := ['$vexe -o v_g -g v.v',
|
v_build_commands := ['$vexe -o v_g -g cmd/v',
|
||||||
'$vexe -o v_prod_g -prod -g v.v',
|
'$vexe -o v_prod_g -prod -g cmd/v',
|
||||||
'$vexe -o v_cg -cg v.v',
|
'$vexe -o v_cg -cg cmd/v',
|
||||||
'$vexe -o v_prod_cg -prod -cg v.v',
|
'$vexe -o v_prod_cg -prod -cg cmd/v',
|
||||||
'$vexe -o v_prod -prod v.v',
|
'$vexe -o v_prod -prod cmd/v',
|
||||||
]
|
]
|
||||||
mut bmark := benchmark.new_benchmark()
|
mut bmark := benchmark.new_benchmark()
|
||||||
for cmd in v_build_commands {
|
for cmd in v_build_commands {
|
|
@ -92,7 +92,7 @@ pub mut:
|
||||||
commit_vc_hash string // the git commit of the vc repo, corresponding to commit_v__hash
|
commit_vc_hash string // the git commit of the vc repo, corresponding to commit_v__hash
|
||||||
vexename string // v or v.exe
|
vexename string // v or v.exe
|
||||||
vexepath string // the full absolute path to the prepared v/v.exe
|
vexepath string // the full absolute path to the prepared v/v.exe
|
||||||
vvlocation string // v.v or compiler/ , depending on v version
|
vvlocation string // v.v or compiler/ or cmd/v, depending on v version
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (vgit_context mut VGitContext) compile_oldv_if_needed() {
|
pub fn (vgit_context mut VGitContext) compile_oldv_if_needed() {
|
||||||
|
@ -117,7 +117,11 @@ pub fn (vgit_context mut VGitContext) compile_oldv_if_needed() {
|
||||||
v_commithash,vccommit_before := vgit.prepare_vc_source(vgit_context.path_vc, vgit_context.path_v, vgit_context.commit_v)
|
v_commithash,vccommit_before := vgit.prepare_vc_source(vgit_context.path_vc, vgit_context.path_v, vgit_context.commit_v)
|
||||||
vgit_context.commit_v__hash = v_commithash
|
vgit_context.commit_v__hash = v_commithash
|
||||||
vgit_context.commit_vc_hash = vccommit_before
|
vgit_context.commit_vc_hash = vccommit_before
|
||||||
|
if os.exists('cmd/v') {
|
||||||
|
vgit_context.vvlocation = 'cmd/v'
|
||||||
|
} else {
|
||||||
vgit_context.vvlocation = if os.exists('v.v') { 'v.v' } else { 'compiler' }
|
vgit_context.vvlocation = if os.exists('v.v') { 'v.v' } else { 'compiler' }
|
||||||
|
}
|
||||||
if os.is_dir(vgit_context.path_v) && os.exists(vgit_context.vexepath) {
|
if os.is_dir(vgit_context.path_v) && os.exists(vgit_context.vexepath) {
|
||||||
// already compiled, so no need to compile v again
|
// already compiled, so no need to compile v again
|
||||||
return
|
return
|
|
@ -19,7 +19,7 @@ const (
|
||||||
git checkout known_good_commit
|
git checkout known_good_commit
|
||||||
git bisect good
|
git bisect good
|
||||||
## Now git will automatically checkout a middle commit between the bad and the good
|
## Now git will automatically checkout a middle commit between the bad and the good
|
||||||
tools/oldv HEAD --command="run commands in oldv folder, to verify if the commit is good or bad"
|
cmd/tools/oldv HEAD --command="run commands in oldv folder, to verify if the commit is good or bad"
|
||||||
## See what the result is, and either do: ...
|
## See what the result is, and either do: ...
|
||||||
git bisect good
|
git bisect good
|
||||||
## ... or do:
|
## ... or do:
|
|
@ -126,7 +126,9 @@ fn (c &Context) prepare_v(cdir string, commit string) {
|
||||||
vversion := scripting.run('$cdir/v --version')
|
vversion := scripting.run('$cdir/v --version')
|
||||||
vcommit := scripting.run('git rev-parse --short --verify HEAD')
|
vcommit := scripting.run('git rev-parse --short --verify HEAD')
|
||||||
println('V version is: ${vversion} , local source commit: ${vcommit}')
|
println('V version is: ${vversion} , local source commit: ${vcommit}')
|
||||||
if vgit_context.vvlocation == 'v.v' {
|
if vgit_context.vvlocation == 'cmd/v' {
|
||||||
|
println('Source lines of the compiler: ' + scripting.run('wc cmd/v/*.v vlib/compiler/*.v | tail -n -1'))
|
||||||
|
} else if vgit_context.vvlocation == 'v.v' {
|
||||||
println('Source lines of the compiler: ' + scripting.run('wc v.v vlib/compiler/*.v | tail -n -1'))
|
println('Source lines of the compiler: ' + scripting.run('wc v.v vlib/compiler/*.v | tail -n -1'))
|
||||||
}else{
|
}else{
|
||||||
println('Source lines of the compiler: ' + scripting.run('wc compiler/*.v | tail -n -1'))
|
println('Source lines of the compiler: ' + scripting.run('wc compiler/*.v | tail -n -1'))
|
||||||
|
@ -136,8 +138,18 @@ fn (c &Context) prepare_v(cdir string, commit string) {
|
||||||
fn (c Context) compare_v_performance(label string, commands []string) string {
|
fn (c Context) compare_v_performance(label string, commands []string) string {
|
||||||
println('---------------------------------------------------------------------------------')
|
println('---------------------------------------------------------------------------------')
|
||||||
println('Compare v performance when doing the following commands ($label):')
|
println('Compare v performance when doing the following commands ($label):')
|
||||||
source_location_a := if os.exists('$c.a/v.v') { 'v.v ' } else { 'compiler/ ' }
|
mut source_location_a := ''
|
||||||
source_location_b := if os.exists('$c.b/v.v') { 'v.v ' } else { 'compiler/ ' }
|
mut source_location_b := ''
|
||||||
|
if os.exists('$c.a/cmd/v') {
|
||||||
|
source_location_a = 'cmd/v'
|
||||||
|
} else {
|
||||||
|
source_location_a = if os.exists('$c.a/v.v') { 'v.v ' } else { 'compiler/ ' }
|
||||||
|
}
|
||||||
|
if os.exists('$c.b/cmd/v') {
|
||||||
|
source_location_b = 'cmd/v'
|
||||||
|
} else {
|
||||||
|
source_location_b = if os.exists('$c.b/v.v') { 'v.v ' } else { 'compiler/ ' }
|
||||||
|
}
|
||||||
timestamp_a,_ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.a/ ; git rev-list -n1 --timestamp HEAD'))
|
timestamp_a,_ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.a/ ; git rev-list -n1 --timestamp HEAD'))
|
||||||
timestamp_b,_ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.b/ ; git rev-list -n1 --timestamp HEAD'))
|
timestamp_b,_ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.b/ ; git rev-list -n1 --timestamp HEAD'))
|
||||||
debug_option_a := if timestamp_a > 1570877641 { '-g ' } else { '-debug ' }
|
debug_option_a := if timestamp_a > 1570877641 { '-g ' } else { '-debug ' }
|
|
@ -1,28 +1,28 @@
|
||||||
# V preludes:
|
# V preludes:
|
||||||
|
|
||||||
The tools/preludes/ contains small v code snippets, that V uses when
|
The cmd/tools/preludes/ contains small v code snippets, that V uses when
|
||||||
compiling certain v programs. V adds the files below automatically itself.
|
compiling certain v programs. V adds the files below automatically itself.
|
||||||
Each file is used in different situations (see below).
|
Each file is used in different situations (see below).
|
||||||
|
|
||||||
NB: preludes are *NOT* intended to be used by user programs/modules.
|
NB: preludes are *NOT* intended to be used by user programs/modules.
|
||||||
The folder tools/preludes/ is *NOT* a v module.
|
The folder cmd/tools/preludes/ is *NOT* a v module.
|
||||||
|
|
||||||
## Details:
|
## Details:
|
||||||
|
|
||||||
### tools/preludes/live_main.v
|
### cmd/tools/preludes/live_main.v
|
||||||
Used when compiling live programs. This file is used by the main executable
|
Used when compiling live programs. This file is used by the main executable
|
||||||
live program, that starts the file change monitoring thread. Each live program
|
live program, that starts the file change monitoring thread. Each live program
|
||||||
needs module `os` and module `time`, in order for the background file change
|
needs module `os` and module `time`, in order for the background file change
|
||||||
monitoring thread to work properly.
|
monitoring thread to work properly.
|
||||||
|
|
||||||
### tools/preludes/live_shared.v
|
### cmd/tools/preludes/live_shared.v
|
||||||
Used when compiling live programs, for the shared library portion of the live
|
Used when compiling live programs, for the shared library portion of the live
|
||||||
programs, that is reloaded each time the code is changed.
|
programs, that is reloaded each time the code is changed.
|
||||||
|
|
||||||
### tools/preludes/tests_assertions.v
|
### cmd/tools/preludes/tests_assertions.v
|
||||||
Used when compiling `_test.v` programs.
|
Used when compiling `_test.v` programs.
|
||||||
It specifies how failed assertions will look.
|
It specifies how failed assertions will look.
|
||||||
|
|
||||||
### tools/preludes/tests_with_stats.v
|
### cmd/tools/preludes/tests_with_stats.v
|
||||||
Used when compiling `_test.v` programs with -stats option.
|
Used when compiling `_test.v` programs with -stats option.
|
||||||
It specifies how the result will appear ('assert' vs 'asserts' and so on).
|
It specifies how the result will appear ('assert' vs 'asserts' and so on).
|
|
@ -8,7 +8,7 @@ import (
|
||||||
fn main() {
|
fn main() {
|
||||||
args := os.args
|
args := os.args
|
||||||
args_string := args[1..].join(' ')
|
args_string := args[1..].join(' ')
|
||||||
if testing.v_build_failing(args_string.all_before('build-tools'), 'tools') {
|
if testing.v_build_failing(args_string.all_before('build-tools'), 'cmd/tools') {
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import (
|
||||||
os.cmdline
|
os.cmdline
|
||||||
filepath
|
filepath
|
||||||
compiler
|
compiler
|
||||||
|
v.pref
|
||||||
)
|
)
|
||||||
|
|
||||||
struct FormatOptions {
|
struct FormatOptions {
|
||||||
|
@ -35,8 +36,8 @@ const (
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
toolexe := os.executable()
|
toolexe := os.executable()
|
||||||
compiler.set_vroot_folder(filepath.dir(filepath.dir(toolexe)))
|
compiler.set_vroot_folder(filepath.dir(filepath.dir(filepath.dir(toolexe))))
|
||||||
args := compiler.env_vflags_and_os_args()
|
args := join_flags_and_argument()
|
||||||
foptions := FormatOptions{
|
foptions := FormatOptions{
|
||||||
is_c: '-c' in args
|
is_c: '-c' in args
|
||||||
is_l: '-l' in args
|
is_l: '-l' in args
|
||||||
|
@ -134,10 +135,10 @@ fn main() {
|
||||||
|
|
||||||
fn (foptions &FormatOptions) format_file(file string) {
|
fn (foptions &FormatOptions) format_file(file string) {
|
||||||
tmpfolder := os.tmpdir()
|
tmpfolder := os.tmpdir()
|
||||||
mut compiler_params := []string
|
mut compiler_params := &pref.Preferences{}
|
||||||
target_os := file_to_target_os(file)
|
target_os := file_to_target_os(file)
|
||||||
if target_os != '' {
|
if target_os != '' {
|
||||||
compiler_params << ['-os', target_os]
|
compiler_params.os = pref.os_from_string(target_os)
|
||||||
}
|
}
|
||||||
mut cfile := file
|
mut cfile := file
|
||||||
mut mod_folder_parent := tmpfolder
|
mut mod_folder_parent := tmpfolder
|
||||||
|
@ -158,7 +159,7 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
}
|
}
|
||||||
os.write_file(main_program_file, main_program_content)
|
os.write_file(main_program_file, main_program_content)
|
||||||
cfile = main_program_file
|
cfile = main_program_file
|
||||||
compiler_params << ['-user_mod_path', mod_folder_parent]
|
compiler_params.user_mod_path = mod_folder_parent
|
||||||
}
|
}
|
||||||
if !is_test_file && mod_name == 'main' {
|
if !is_test_file && mod_name == 'main' {
|
||||||
// NB: here, file is guaranted to be a main. We do not know however
|
// NB: here, file is guaranted to be a main. We do not know however
|
||||||
|
@ -166,7 +167,10 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
// project, like vorum or vid.
|
// project, like vorum or vid.
|
||||||
cfile = get_compile_name_of_potential_v_project(cfile)
|
cfile = get_compile_name_of_potential_v_project(cfile)
|
||||||
}
|
}
|
||||||
compiler_params << cfile
|
compiler_params.path = cfile
|
||||||
|
compiler_params.mod = mod_name
|
||||||
|
compiler_params.is_test = is_test_file
|
||||||
|
compiler_params.is_script = file.ends_with('.v') || file.ends_with('.vsh')
|
||||||
if foptions.is_verbose {
|
if foptions.is_verbose {
|
||||||
eprintln('vfmt format_file: file: $file')
|
eprintln('vfmt format_file: file: $file')
|
||||||
eprintln('vfmt format_file: cfile: $cfile')
|
eprintln('vfmt format_file: cfile: $cfile')
|
||||||
|
@ -176,9 +180,15 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
eprintln('vfmt format_file: mod_folder: $mod_folder')
|
eprintln('vfmt format_file: mod_folder: $mod_folder')
|
||||||
eprintln('vfmt format_file: mod_folder_parent: $mod_folder_parent')
|
eprintln('vfmt format_file: mod_folder_parent: $mod_folder_parent')
|
||||||
eprintln('vfmt format_file: use_tmp_main_program: $use_tmp_main_program')
|
eprintln('vfmt format_file: use_tmp_main_program: $use_tmp_main_program')
|
||||||
eprintln('vfmt format_file: compiler_params: $compiler_params')
|
eprintln('vfmt format_file: compiler_params: ')
|
||||||
|
print_compiler_options( compiler_params )
|
||||||
eprintln('-------------------------------------------')
|
eprintln('-------------------------------------------')
|
||||||
}
|
}
|
||||||
|
compiler_params.fill_with_defaults()
|
||||||
|
if foptions.is_verbose {
|
||||||
|
eprintln('vfmt format_file: compiler_params: AFTER fill_with_defaults() ')
|
||||||
|
print_compiler_options( compiler_params )
|
||||||
|
}
|
||||||
formatted_file_path := foptions.compile_file(file, compiler_params)
|
formatted_file_path := foptions.compile_file(file, compiler_params)
|
||||||
if use_tmp_main_program {
|
if use_tmp_main_program {
|
||||||
if !foptions.is_debug {
|
if !foptions.is_debug {
|
||||||
|
@ -188,6 +198,22 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
eprintln('${FORMATTED_FILE_TOKEN}${formatted_file_path}')
|
eprintln('${FORMATTED_FILE_TOKEN}${formatted_file_path}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_compiler_options( compiler_params &pref.Preferences ) {
|
||||||
|
eprintln(' os: ' + compiler_params.os.str() )
|
||||||
|
eprintln(' ccompiler: $compiler_params.ccompiler' )
|
||||||
|
eprintln(' mod: $compiler_params.mod ')
|
||||||
|
eprintln(' path: $compiler_params.path ')
|
||||||
|
eprintln(' out_name: $compiler_params.out_name ')
|
||||||
|
eprintln(' vroot: $compiler_params.vroot ')
|
||||||
|
eprintln(' vpath: $compiler_params.vpath ')
|
||||||
|
eprintln(' vlib_path: $compiler_params.vlib_path ')
|
||||||
|
eprintln(' out_name: $compiler_params.out_name ')
|
||||||
|
eprintln(' umpath: $compiler_params.user_mod_path ')
|
||||||
|
eprintln(' cflags: $compiler_params.cflags ')
|
||||||
|
eprintln(' is_test: $compiler_params.is_test ')
|
||||||
|
eprintln(' is_script: $compiler_params.is_script ')
|
||||||
|
}
|
||||||
|
|
||||||
fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path string) {
|
fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path string) {
|
||||||
if formatted_file_path.len == 0 {
|
if formatted_file_path.len == 0 {
|
||||||
return
|
return
|
||||||
|
@ -238,7 +264,7 @@ fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage() {
|
fn usage() {
|
||||||
print('Usage: tools/vfmt [flags] fmt path_to_source.v [path_to_other_source.v]
|
print('Usage: cmd/tools/vfmt [flags] fmt path_to_source.v [path_to_other_source.v]
|
||||||
Formats the given V source files, and prints their formatted source to stdout.
|
Formats the given V source files, and prints their formatted source to stdout.
|
||||||
Options:
|
Options:
|
||||||
-c check if file is already formatted.
|
-c check if file is already formatted.
|
||||||
|
@ -261,12 +287,13 @@ fn find_working_diff_command() ?string {
|
||||||
return error('no working diff command found')
|
return error('no working diff command found')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (foptions &FormatOptions) compile_file(file string, compiler_params []string) string {
|
fn (foptions &FormatOptions) compile_file(file string, compiler_params &pref.Preferences) string {
|
||||||
if foptions.is_verbose {
|
if foptions.is_verbose {
|
||||||
eprintln('> new_v_compiler_with_args file: ' + file)
|
eprintln('> new_v_compiler_with_args file: $file')
|
||||||
eprintln('> new_v_compiler_with_args compiler_params: ' + compiler_params.join(' '))
|
eprintln('> new_v_compiler_with_args compiler_params:')
|
||||||
|
print_compiler_options( compiler_params )
|
||||||
}
|
}
|
||||||
mut v := compiler.new_v_compiler_with_args(compiler_params)
|
mut v := compiler.new_v(compiler_params)
|
||||||
v.v_fmt_file = file
|
v.v_fmt_file = file
|
||||||
if foptions.is_all {
|
if foptions.is_all {
|
||||||
v.v_fmt_all = true
|
v.v_fmt_all = true
|
||||||
|
@ -360,3 +387,28 @@ fn get_compile_name_of_potential_v_project(file string) string {
|
||||||
}
|
}
|
||||||
return pfolder
|
return pfolder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO Move join_flags_and_argument() and non_empty() into `cmd/internal` when v.mod work correctly
|
||||||
|
//to prevent code duplication with `cmd/v` (cmd/v/flag.v)
|
||||||
|
fn join_flags_and_argument() []string {
|
||||||
|
vosargs := os.getenv('VOSARGS')
|
||||||
|
if vosargs != '' {
|
||||||
|
return non_empty(vosargs.split(' '))
|
||||||
|
}
|
||||||
|
|
||||||
|
mut args := []string
|
||||||
|
vflags := os.getenv('VFLAGS')
|
||||||
|
if vflags != '' {
|
||||||
|
args << os.args[0]
|
||||||
|
args << vflags.split(' ')
|
||||||
|
if os.args.len > 1 {
|
||||||
|
args << os.args[1..]
|
||||||
|
}
|
||||||
|
return non_empty(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
return non_empty(os.args)
|
||||||
|
}
|
||||||
|
fn non_empty(arg []string) []string {
|
||||||
|
return arg.filter(it != '')
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import (
|
||||||
strings
|
strings
|
||||||
filepath
|
filepath
|
||||||
compiler
|
compiler
|
||||||
|
v.pref
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -32,7 +33,11 @@ fn analyze_v_file(file string) {
|
||||||
println('$hash $file $hash')
|
println('$hash $file $hash')
|
||||||
|
|
||||||
// main work:
|
// main work:
|
||||||
mut v := compiler.new_v_compiler_with_args([file])
|
mut pref := &pref.Preferences{
|
||||||
|
path: file
|
||||||
|
}
|
||||||
|
pref.fill_with_defaults()
|
||||||
|
mut v := compiler.new_v(pref)
|
||||||
v.add_v_files_to_compile()
|
v.add_v_files_to_compile()
|
||||||
for f in v.files { v.parse(f, .decl) }
|
for f in v.files { v.parse(f, .decl) }
|
||||||
fi := v.get_file_parser_index( file ) or { panic(err) }
|
fi := v.get_file_parser_index( file ) or { panic(err) }
|
||||||
|
@ -51,7 +56,7 @@ fn analyze_v_file(file string) {
|
||||||
|
|
||||||
fn main(){
|
fn main(){
|
||||||
toolexe := os.executable()
|
toolexe := os.executable()
|
||||||
compiler.set_vroot_folder( filepath.dir(filepath.dir(toolexe)) )
|
compiler.set_vroot_folder(filepath.dir(filepath.dir(filepath.dir(toolexe))))
|
||||||
|
|
||||||
mut fp := flag.new_flag_parser(os.args)
|
mut fp := flag.new_flag_parser(os.args)
|
||||||
fp.application(filepath.filename(toolexe))
|
fp.application(filepath.filename(toolexe))
|
|
@ -33,8 +33,8 @@ fn v_test_compiler(vargs string) {
|
||||||
|
|
||||||
// Make sure v.c can be compiled without warnings
|
// Make sure v.c can be compiled without warnings
|
||||||
$if macos {
|
$if macos {
|
||||||
if os.exists('/v.v') {
|
if os.exists('/cmd/v') {
|
||||||
os.system('$vexe -o v.c v.v')
|
os.system('$vexe -o v.c cmd/v')
|
||||||
if os.system('cc -Werror v.c') != 0 {
|
if os.system('cc -Werror v.c') != 0 {
|
||||||
eprintln('cc failed to build v.c without warnings')
|
eprintln('cc failed to build v.c without warnings')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
@ -42,7 +42,7 @@ fn v_test_compiler(vargs string) {
|
||||||
eprintln('v.c can be compiled without warnings. This is good :)')
|
eprintln('v.c can be compiled without warnings. This is good :)')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
building_tools_failed := testing.v_build_failing(vargs, 'tools')
|
building_tools_failed := testing.v_build_failing(vargs, 'cmd/tools')
|
||||||
eprintln('')
|
eprintln('')
|
||||||
testing.eheader('Testing all _test.v files...')
|
testing.eheader('Testing all _test.v files...')
|
||||||
mut compiler_test_session := testing.new_test_session(vargs)
|
mut compiler_test_session := testing.new_test_session(vargs)
|
|
@ -7,14 +7,14 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
known_failing_exceptions = ['./examples/vweb/vweb_example.v',
|
known_failing_exceptions = ['./examples/vweb/vweb_example.v',
|
||||||
'./tools/gen_vc.v',
|
'./cmd/tools/gen_vc.v',
|
||||||
'./tools/modules/vgit/vgit.v', // generics
|
'./cmd/tools/modules/vgit/vgit.v', // generics
|
||||||
'./tools/preludes/live_main.v',
|
'./cmd/tools/preludes/live_main.v',
|
||||||
'./tools/preludes/live_shared.v',
|
'./cmd/tools/preludes/live_shared.v',
|
||||||
'./tools/preludes/tests_assertions.v',
|
'./cmd/tools/preludes/tests_assertions.v',
|
||||||
'./tools/preludes/tests_with_stats.v',
|
'./cmd/tools/preludes/tests_with_stats.v',
|
||||||
'./tools/performance_compare.v', // generics
|
'./cmd/tools/performance_compare.v', // generics
|
||||||
'./tools/oldv.v', // generics
|
'./cmd/tools/oldv.v', // generics
|
||||||
'./tutorials/code/blog/article.v',
|
'./tutorials/code/blog/article.v',
|
||||||
'./tutorials/code/blog/blog.v',
|
'./tutorials/code/blog/blog.v',
|
||||||
'./vlib/arrays/arrays.v',
|
'./vlib/arrays/arrays.v',
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright (c) 2019-2020 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 main
|
||||||
|
|
||||||
|
import (
|
||||||
|
benchmark
|
||||||
|
os
|
||||||
|
os.cmdline
|
||||||
|
)
|
||||||
|
|
||||||
|
fn compile(command string, args []string) {
|
||||||
|
// Construct the V object from command line arguments
|
||||||
|
mut v := new_v(args)
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
println(args)
|
||||||
|
}
|
||||||
|
if command == 'run' {
|
||||||
|
// always recompile for now, too error prone to skip recompilation otherwise
|
||||||
|
// for example for -repl usage, especially when piping lines to v
|
||||||
|
v.compile()
|
||||||
|
run_compiled_executable_and_exit(v, args)
|
||||||
|
}
|
||||||
|
mut tmark := benchmark.new_benchmark()
|
||||||
|
if v.pref.x64 {
|
||||||
|
v.compile_x64()
|
||||||
|
}
|
||||||
|
else if v.pref.v2 {
|
||||||
|
v.compile2()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.compile()
|
||||||
|
}
|
||||||
|
if v.pref.is_stats {
|
||||||
|
tmark.stop()
|
||||||
|
println('compilation took: ' + tmark.total_duration().str() + 'ms')
|
||||||
|
}
|
||||||
|
if v.pref.is_test {
|
||||||
|
run_compiled_executable_and_exit(v, args)
|
||||||
|
}
|
||||||
|
v.finalize_compilation()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_compiled_executable_and_exit(v &compiler.V, args []string) {
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
println('============ running $v.pref.out_name ============')
|
||||||
|
}
|
||||||
|
mut cmd := '"${v.pref.out_name}"'
|
||||||
|
args_after_no_options := cmdline.only_non_options( cmdline.after(args,['run','test']) )
|
||||||
|
if args_after_no_options.len > 1 {
|
||||||
|
cmd += ' ' + args_after_no_options[1..].join(' ')
|
||||||
|
}
|
||||||
|
if v.pref.is_test {
|
||||||
|
ret := os.system(cmd)
|
||||||
|
if ret != 0 {
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v.pref.is_run {
|
||||||
|
ret := os.system(cmd)
|
||||||
|
// TODO: make the runner wrapping as transparent as possible
|
||||||
|
// (i.e. use execve when implemented). For now though, the runner
|
||||||
|
// just returns the same exit code as the child process.
|
||||||
|
exit(ret)
|
||||||
|
}
|
||||||
|
exit(0)
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
// Copyright (c) 2019-2020 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 main
|
||||||
|
|
||||||
|
import (
|
||||||
|
compiler
|
||||||
|
filepath
|
||||||
|
os
|
||||||
|
os.cmdline
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
|
//TODO Cleanup this file. This file ended up like a dump for functions that do not belong in `compiler`.
|
||||||
|
//Maybe restructure the functions below into different V files
|
||||||
|
|
||||||
|
pub fn new_v(args []string) &compiler.V {
|
||||||
|
// Create modules dirs if they are missing
|
||||||
|
if !os.is_dir(compiler.v_modules_path) {
|
||||||
|
os.mkdir(compiler.v_modules_path)or{
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
os.mkdir('$compiler.v_modules_path${os.path_separator}cache')or{
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vroot := filepath.dir(vexe_path())
|
||||||
|
// optional, custom modules search path
|
||||||
|
user_mod_path := cmdline.option(args, '-user_mod_path', '')
|
||||||
|
vlib_path := cmdline.option(args, '-vlib-path', '')
|
||||||
|
vpath := cmdline.option(args, '-vpath', '')
|
||||||
|
target_os := cmdline.option(args, '-os', '')
|
||||||
|
if target_os == 'msvc' {
|
||||||
|
// notice that `-os msvc` became `-cc msvc`
|
||||||
|
println('V error: use the flag `-cc msvc` to build using msvc')
|
||||||
|
os.flush_stdout()
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
mut out_name := cmdline.option(args, '-o', '')
|
||||||
|
mut dir := args.last()
|
||||||
|
if 'run' in args {
|
||||||
|
args_after_run := cmdline.only_non_options( cmdline.after(args,['run']) )
|
||||||
|
dir = if args_after_run.len>0 { args_after_run[0] } else { '' }
|
||||||
|
}
|
||||||
|
if dir == 'v.v' {
|
||||||
|
println('looks like you are trying to build V with an old command')
|
||||||
|
println('use `v -o v cmd/v` instead of `v -o v v.v`')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
if dir.ends_with(os.path_separator) {
|
||||||
|
dir = dir.all_before_last(os.path_separator)
|
||||||
|
}
|
||||||
|
if dir.starts_with('.$os.path_separator') {
|
||||||
|
dir = dir[2..]
|
||||||
|
}
|
||||||
|
if args.len < 2 {
|
||||||
|
dir = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// build mode
|
||||||
|
mut build_mode := pref.BuildMode.default_mode
|
||||||
|
mut mod := ''
|
||||||
|
joined_args := args.join(' ')
|
||||||
|
if joined_args.contains('build module ') {
|
||||||
|
build_mode = .build_module
|
||||||
|
os.chdir(vroot)
|
||||||
|
// v build module ~/v/os => os.o
|
||||||
|
mod_path := if dir.contains('vlib') { dir.all_after('vlib' + os.path_separator) } else if dir.starts_with('.\\') || dir.starts_with('./') { dir[2..] } else if dir.starts_with(os.path_separator) { dir.all_after(os.path_separator) } else { dir }
|
||||||
|
mod = mod_path.replace(os.path_separator, '.')
|
||||||
|
println('Building module "${mod}" (dir="$dir")...')
|
||||||
|
// out_name = '$TmpPath/vlib/${base}.o'
|
||||||
|
if !out_name.ends_with('.c') {
|
||||||
|
out_name = mod
|
||||||
|
}
|
||||||
|
// Cross compiling? Use separate dirs for each os
|
||||||
|
/*
|
||||||
|
if target_os != os.user_os() {
|
||||||
|
os.mkdir('$TmpPath/vlib/$target_os') or { panic(err) }
|
||||||
|
out_name = '$TmpPath/vlib/$target_os/${base}.o'
|
||||||
|
println('target_os=$target_os user_os=${os.user_os()}')
|
||||||
|
println('!Cross compiling $out_name')
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
// `v -o dir/exec`, create "dir/" if it doesn't exist
|
||||||
|
if out_name.contains(os.path_separator) {
|
||||||
|
d := out_name.all_before_last(os.path_separator)
|
||||||
|
if !os.is_dir(d) {
|
||||||
|
println('creating a new directory "$d"')
|
||||||
|
os.mkdir(d)or{
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// println('VROOT=$vroot')
|
||||||
|
cflags := cmdline.many_values(args, '-cflags').join(' ')
|
||||||
|
|
||||||
|
defines := cmdline.many_values(args, '-d')
|
||||||
|
compile_defines, compile_defines_all := parse_defines( defines )
|
||||||
|
|
||||||
|
rdir := os.realpath(dir)
|
||||||
|
rdir_name := filepath.filename(rdir)
|
||||||
|
if '-bare' in args {
|
||||||
|
println('V error: use -freestanding instead of -bare')
|
||||||
|
os.flush_stdout()
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
is_repl := '-repl' in args
|
||||||
|
ccompiler := cmdline.option(args, '-cc', '')
|
||||||
|
mut pref := &pref.Preferences{
|
||||||
|
os: pref.os_from_string(target_os)
|
||||||
|
is_so: '-shared' in args
|
||||||
|
is_solive: '-solive' in args
|
||||||
|
is_prod: '-prod' in args
|
||||||
|
is_verbose: '-verbose' in args || '--verbose' in args
|
||||||
|
is_debug: '-g' in args || '-cg' in args
|
||||||
|
is_vlines: '-g' in args && !('-cg' in args)
|
||||||
|
is_keep_c: '-keep_c' in args
|
||||||
|
is_pretty_c: '-pretty_c' in args
|
||||||
|
is_cache: '-cache' in args
|
||||||
|
is_stats: '-stats' in args
|
||||||
|
obfuscate: '-obf' in args
|
||||||
|
is_prof: '-prof' in args
|
||||||
|
is_live: '-live' in args
|
||||||
|
sanitize: '-sanitize' in args
|
||||||
|
// nofmt: '-nofmt' in args
|
||||||
|
|
||||||
|
show_c_cmd: '-show_c_cmd' in args
|
||||||
|
translated: 'translated' in args
|
||||||
|
is_run: 'run' in args
|
||||||
|
autofree: '-autofree' in args
|
||||||
|
compress: '-compress' in args
|
||||||
|
enable_globals: '--enable-globals' in args
|
||||||
|
fast: '-fast' in args
|
||||||
|
is_bare: '-freestanding' in args
|
||||||
|
x64: '-x64' in args
|
||||||
|
output_cross_c: '-output-cross-platform-c' in args
|
||||||
|
prealloc: '-prealloc' in args
|
||||||
|
is_repl: is_repl
|
||||||
|
build_mode: build_mode
|
||||||
|
cflags: cflags
|
||||||
|
ccompiler: ccompiler
|
||||||
|
building_v: !is_repl && (rdir_name == 'compiler' || rdir_name == 'v.v' || rdir_name == 'vfmt.v' || rdir_name == 'cmd/v' || dir.contains('vlib'))
|
||||||
|
// is_fmt: comptime_define == 'vfmt'
|
||||||
|
|
||||||
|
user_mod_path: user_mod_path
|
||||||
|
vlib_path: vlib_path
|
||||||
|
vpath: vpath
|
||||||
|
v2: '-v2' in args
|
||||||
|
vroot: vroot
|
||||||
|
out_name: out_name
|
||||||
|
path: dir
|
||||||
|
compile_defines: compile_defines
|
||||||
|
compile_defines_all: compile_defines_all
|
||||||
|
mod: mod
|
||||||
|
}
|
||||||
|
if pref.is_verbose || pref.is_debug {
|
||||||
|
println('C compiler=$pref.ccompiler')
|
||||||
|
}
|
||||||
|
$if !linux {
|
||||||
|
if pref.is_bare && !out_name.ends_with('.c') {
|
||||||
|
println('V error: -freestanding only works on Linux for now')
|
||||||
|
os.flush_stdout()
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pref.fill_with_defaults()
|
||||||
|
|
||||||
|
// v.exe's parent directory should contain vlib
|
||||||
|
if !os.is_dir(pref.vlib_path) || !os.is_dir(pref.vlib_path + os.path_separator + 'builtin') {
|
||||||
|
// println('vlib not found, downloading it...')
|
||||||
|
/*
|
||||||
|
ret := os.system('git clone --depth=1 https://github.com/vlang/v .')
|
||||||
|
if ret != 0 {
|
||||||
|
println('failed to `git clone` vlib')
|
||||||
|
println('make sure you are online and have git installed')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
println('vlib not found. It should be next to the V executable.')
|
||||||
|
println('Go to https://vlang.io to install V.')
|
||||||
|
println('(os.executable=${os.executable()} vlib_path=$pref.vlib_path vexe_path=${vexe_path()}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pref.is_script && !os.exists(dir) {
|
||||||
|
println('`$dir` does not exist')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return compiler.new_v(pref)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_c_compiler_thirdparty_options(args []string) string {
|
||||||
|
mut cflags := cmdline.many_values(args,'-cflags')
|
||||||
|
$if !windows {
|
||||||
|
cflags << '-fPIC'
|
||||||
|
}
|
||||||
|
if '-m32' in args {
|
||||||
|
cflags << '-m32'
|
||||||
|
}
|
||||||
|
return cflags.join(' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_defines(defines []string) ([]string,[]string) {
|
||||||
|
// '-d abc -d xyz=1 -d qwe=0' should produce:
|
||||||
|
// compile_defines: ['abc','xyz']
|
||||||
|
// compile_defines_all ['abc','xyz','qwe']
|
||||||
|
mut compile_defines := []string
|
||||||
|
mut compile_defines_all := []string
|
||||||
|
for dfn in defines {
|
||||||
|
dfn_parts := dfn.split('=')
|
||||||
|
if dfn_parts.len == 1 {
|
||||||
|
compile_defines << dfn
|
||||||
|
compile_defines_all << dfn
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if dfn_parts.len == 2 {
|
||||||
|
compile_defines_all << dfn_parts[0]
|
||||||
|
if dfn_parts[1] == '1' {
|
||||||
|
compile_defines << dfn_parts[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compile_defines, compile_defines_all
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright (c) 2019-2020 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 main
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
const (
|
||||||
|
//list_of_flags contains a list of flags where an argument is expected past it.
|
||||||
|
list_of_flags = [
|
||||||
|
'-o', '-os', '-cc', '-cflags', '-d'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
fn get_basic_command_and_option(args []string) (string, []string) {
|
||||||
|
mut option := []string
|
||||||
|
for i, arg in args {
|
||||||
|
if i == 0 {
|
||||||
|
//Skip executable
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if arg == '--' {
|
||||||
|
//End of list of options. The next one is the command.
|
||||||
|
if i+1 < os.args.len {
|
||||||
|
return os.args[i+1], option
|
||||||
|
}
|
||||||
|
//There's no option past this
|
||||||
|
return '', option
|
||||||
|
}
|
||||||
|
if arg in list_of_flags {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if arg[0] == `-` {
|
||||||
|
option << arg
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
//It's not a flag. We did not skip it. It's a command.
|
||||||
|
return arg, option
|
||||||
|
}
|
||||||
|
|
||||||
|
//There's no arguments that were not part of a flag.
|
||||||
|
return '', option
|
||||||
|
}
|
||||||
|
|
||||||
|
fn non_empty(arg []string) []string {
|
||||||
|
return arg.filter(it != '')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn join_flags_and_argument() []string {
|
||||||
|
vosargs := os.getenv('VOSARGS')
|
||||||
|
if vosargs != '' {
|
||||||
|
return non_empty(vosargs.split(' '))
|
||||||
|
}
|
||||||
|
|
||||||
|
mut args := []string
|
||||||
|
vflags := os.getenv('VFLAGS')
|
||||||
|
if vflags != '' {
|
||||||
|
args << os.args[0]
|
||||||
|
args << vflags.split(' ')
|
||||||
|
if os.args.len > 1 {
|
||||||
|
args << os.args[1..]
|
||||||
|
}
|
||||||
|
return non_empty(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
return non_empty(os.args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vexe_path() string {
|
||||||
|
vexe := os.getenv('VEXE')
|
||||||
|
if vexe != '' {
|
||||||
|
return vexe
|
||||||
|
}
|
||||||
|
real_vexe_path := os.realpath(os.executable())
|
||||||
|
os.setenv('VEXE', real_vexe_path, true)
|
||||||
|
return real_vexe_path
|
||||||
|
}
|
|
@ -1,8 +1,16 @@
|
||||||
module compiler
|
module main
|
||||||
|
|
||||||
pub const (
|
const (
|
||||||
help_text = 'Usage: v [options/commands] [file.v | directory]
|
help_text = 'Usage: v [options/commands] [file.v | directory]
|
||||||
|
|
||||||
|
To run V in REPL mode, run V without any arguments.
|
||||||
|
To compile a directory/file, pass it as the only argument.
|
||||||
|
|
||||||
|
To run a directory/file, use `v run [file.v | directory]`. V will compile and run it for you.
|
||||||
|
|
||||||
|
This help message is only intended to be a quick start guide. For a comprehensive help message, use `v help --verbose`.'
|
||||||
|
verbose_help_text = 'Usage: v [options/commands] [file.v | directory]
|
||||||
|
|
||||||
When V is run without any arguments, it is run in REPL mode.
|
When V is run without any arguments, it is run in REPL mode.
|
||||||
|
|
||||||
When given a .v file, it will be compiled. The executable will have the
|
When given a .v file, it will be compiled. The executable will have the
|
|
@ -1,23 +1,27 @@
|
||||||
module compiler
|
// Copyright (c) 2019-2020 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 main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
os
|
compiler
|
||||||
filepath
|
filepath
|
||||||
|
os
|
||||||
)
|
)
|
||||||
|
|
||||||
pub fn launch_tool(tname string, cmdname string) {
|
fn launch_tool(is_verbose bool, tname string, cmdname string) {
|
||||||
is_verbose := '-verbose' in os.args || '--verbose' in os.args
|
|
||||||
vexe := vexe_path()
|
vexe := vexe_path()
|
||||||
vroot := filepath.dir(vexe)
|
vroot := filepath.dir(vexe)
|
||||||
set_vroot_folder( vroot ) // needed by tools to find back v
|
compiler.set_vroot_folder(vroot)
|
||||||
|
|
||||||
mut tname_index := os.args.index(cmdname)
|
mut tname_index := os.args.index(cmdname)
|
||||||
if tname_index == -1 {
|
if tname_index == -1 {
|
||||||
tname_index = os.args.len
|
tname_index = os.args.len
|
||||||
}
|
}
|
||||||
mut compilation_options := os.args[1..tname_index].clone()
|
mut compilation_options := os.args[1..tname_index].clone()
|
||||||
tool_args := os.args[1..].join(' ')
|
tool_args := os.args[1..].join(' ')
|
||||||
tool_exe := os.realpath('$vroot/tools/$tname')
|
tool_exe := os.realpath('$vroot/cmd/tools/$tname')
|
||||||
tool_source := os.realpath('$vroot/tools/${tname}.v')
|
tool_source := os.realpath('$vroot/cmd/tools/${tname}.v')
|
||||||
tool_command := '"$tool_exe" $tool_args'
|
tool_command := '"$tool_exe" $tool_args'
|
||||||
if is_verbose {
|
if is_verbose {
|
||||||
eprintln('launch_tool vexe : $vroot')
|
eprintln('launch_tool vexe : $vroot')
|
||||||
|
@ -25,28 +29,29 @@ pub fn launch_tool(tname string, cmdname string) {
|
||||||
eprintln('launch_tool tool_args : $tool_args')
|
eprintln('launch_tool tool_args : $tool_args')
|
||||||
eprintln('launch_tool tool_command: $tool_command')
|
eprintln('launch_tool tool_command: $tool_command')
|
||||||
}
|
}
|
||||||
mut tool_should_be_recompiled := false
|
|
||||||
|
mut should_compile := false
|
||||||
if !os.exists(tool_exe) {
|
if !os.exists(tool_exe) {
|
||||||
// fresh checkout
|
should_compile = true
|
||||||
tool_should_be_recompiled = true
|
|
||||||
} else {
|
} else {
|
||||||
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(vexe) {
|
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(vexe) {
|
||||||
// v was recompiled, maybe after v up ...
|
// v was recompiled, maybe after v up ...
|
||||||
// rebuild the tool too just in case
|
// rebuild the tool too just in case
|
||||||
tool_should_be_recompiled = true
|
should_compile = true
|
||||||
}
|
}
|
||||||
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(tool_source) {
|
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(tool_source) {
|
||||||
// the user changed the source code of the tool
|
// the user changed the source code of the tool
|
||||||
tool_should_be_recompiled = true
|
should_compile = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_verbose {
|
if is_verbose {
|
||||||
eprintln('launch_tool tool_should_be_recompiled: $tool_should_be_recompiled')
|
eprintln('launch_tool should_compile: $should_compile')
|
||||||
}
|
}
|
||||||
|
|
||||||
if tool_should_be_recompiled {
|
if should_compile {
|
||||||
if tname == 'vfmt' { compilation_options << ['-d', 'vfmt'] }
|
if tname == 'vfmt' {
|
||||||
|
compilation_options << ['-d', 'vfmt']
|
||||||
|
}
|
||||||
compilation_args := compilation_options.join(' ')
|
compilation_args := compilation_options.join(' ')
|
||||||
compilation_command := '"$vexe" $compilation_args "$tool_source"'
|
compilation_command := '"$vexe" $compilation_args "$tool_source"'
|
||||||
if is_verbose {
|
if is_verbose {
|
||||||
|
@ -61,5 +66,5 @@ pub fn launch_tool(tname string, cmdname string) {
|
||||||
eprintln('launch_tool running tool command: $tool_command ...')
|
eprintln('launch_tool running tool command: $tool_command ...')
|
||||||
}
|
}
|
||||||
|
|
||||||
exit( os.system(tool_command) )
|
exit(os.system(tool_command))
|
||||||
}
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2019-2020 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 main
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
fn create_symlink() {
|
||||||
|
$if windows {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vexe := vexe_path()
|
||||||
|
mut link_path := '/usr/local/bin/v'
|
||||||
|
mut ret := os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
||||||
|
if ret.exit_code == 0 {
|
||||||
|
println('Symlink "$link_path" has been created')
|
||||||
|
}
|
||||||
|
else if os.system('uname -o | grep -q \'[A/a]ndroid\'') == 0 {
|
||||||
|
println('Failed to create symlink "$link_path". Trying again with Termux path for Android.')
|
||||||
|
link_path = '/data/data/com.termux/files/usr/bin/v'
|
||||||
|
ret = os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
||||||
|
if ret.exit_code == 0 {
|
||||||
|
println('Symlink "$link_path" has been created')
|
||||||
|
} else {
|
||||||
|
println('Failed to create symlink "$link_path". Try again with sudo.')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println('Failed to create symlink "$link_path". Try again with sudo.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright (c) 2019-2020 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 main
|
||||||
|
|
||||||
|
import (
|
||||||
|
compiler
|
||||||
|
os
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
simple_cmd = [
|
||||||
|
'fmt',
|
||||||
|
'up',
|
||||||
|
'create',
|
||||||
|
'test', 'test-fmt', 'test-compiler',
|
||||||
|
'bin2v',
|
||||||
|
'repl',
|
||||||
|
'build-tools', 'build-examples', 'build-vbinaries'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
arg := join_flags_and_argument()
|
||||||
|
command, option := get_basic_command_and_option(arg)
|
||||||
|
|
||||||
|
is_verbose := '-verbose' in arg || '--verbose' in arg
|
||||||
|
|
||||||
|
if '-v' in option || '--version' in option || command == 'version' {
|
||||||
|
// Print the version and exit.
|
||||||
|
version_hash := compiler.vhash()
|
||||||
|
println('V $compiler.Version $version_hash')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if '-h' in option || '--help' in option || command == 'help' {
|
||||||
|
if is_verbose {
|
||||||
|
println(verbose_help_text)
|
||||||
|
} else {
|
||||||
|
println(help_text)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_verbose {
|
||||||
|
eprintln('v args: $arg')
|
||||||
|
eprintln('v command: $command')
|
||||||
|
eprintln('v options: $option')
|
||||||
|
}
|
||||||
|
|
||||||
|
if command in simple_cmd {
|
||||||
|
//External tools
|
||||||
|
launch_tool(is_verbose, 'v' + command, command)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if command == 'run' || command == 'build' || command.ends_with('.v') || os.exists(command) {
|
||||||
|
compile(command, arg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
match command {
|
||||||
|
'', '-' {
|
||||||
|
if arg.len == 1 {
|
||||||
|
println('Running REPL as no arguments are provided. For usage information, use `v help`.')
|
||||||
|
}
|
||||||
|
launch_tool(is_verbose, 'vrepl', '')
|
||||||
|
}
|
||||||
|
'translate' {
|
||||||
|
println('Translating C to V will be available in V 0.3 (January)')
|
||||||
|
}
|
||||||
|
'search', 'install', 'update', 'remove' {
|
||||||
|
launch_tool(is_verbose, 'vpm', command)
|
||||||
|
}
|
||||||
|
'get' {
|
||||||
|
println('Use `v install` to install modules from vpm.vlang.io.')
|
||||||
|
}
|
||||||
|
'symlink' {
|
||||||
|
create_symlink()
|
||||||
|
}
|
||||||
|
'doc' {
|
||||||
|
println('Currently unimplemented')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eprintln('v $command: unknown command\nRun "v help" for usage.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
make.bat
8
make.bat
|
@ -35,8 +35,8 @@ if %ERRORLEVEL% NEQ 0 (
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Now using V to build V...
|
echo Now using V to build V...
|
||||||
v2.exe -o v3.exe v.v
|
v2.exe -o v3.exe cmd/v
|
||||||
v3.exe -o v.exe -prod v.v
|
v3.exe -o v.exe -prod cmd/v
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
echo v.exe failed to compile itself - Create an issue at 'https://github.com/vlang'
|
echo v.exe failed to compile itself - Create an issue at 'https://github.com/vlang'
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
@ -77,8 +77,8 @@ if %ERRORLEVEL% NEQ 0 (
|
||||||
)
|
)
|
||||||
|
|
||||||
echo rebuild from source (twice, in case of C definitions changes)
|
echo rebuild from source (twice, in case of C definitions changes)
|
||||||
v2.exe -cc msvc -o v3.exe v.v
|
v2.exe -cc msvc -o v3.exe cmd/v
|
||||||
v3.exe -cc msvc -o v -prod v.v
|
v3.exe -cc msvc -o v -prod cmd/v
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
echo V failed to build itself with error %ERRORLEVEL%
|
echo V failed to build itself with error %ERRORLEVEL%
|
||||||
goto :compileerror
|
goto :compileerror
|
||||||
|
|
140
v.v
140
v.v
|
@ -1,140 +0,0 @@
|
||||||
// Copyright (c) 2019-2020 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 main
|
|
||||||
|
|
||||||
import (
|
|
||||||
compiler
|
|
||||||
benchmark
|
|
||||||
os
|
|
||||||
filepath
|
|
||||||
// v.types
|
|
||||||
// time
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
known_commands = ['run', 'build', 'version', 'doc']
|
|
||||||
simple_tools = ['fmt',
|
|
||||||
'up',
|
|
||||||
'create',
|
|
||||||
'test', 'test-fmt', 'test-compiler',
|
|
||||||
'bin2v',
|
|
||||||
'repl',
|
|
||||||
'build-tools', 'build-examples', 'build-vbinaries']
|
|
||||||
)
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
is_verbose := '-verbose' in os.args || '--verbose' in os.args
|
|
||||||
// t := time.ticks()
|
|
||||||
// defer { println(time.ticks() - t) }
|
|
||||||
args := compiler.env_vflags_and_os_args()
|
|
||||||
options,command := compiler.get_v_options_and_main_command(args)
|
|
||||||
if is_verbose {
|
|
||||||
eprintln('v args: $args')
|
|
||||||
eprintln('v command: $command')
|
|
||||||
eprintln('v options: $options')
|
|
||||||
}
|
|
||||||
// external tool
|
|
||||||
if command in simple_tools {
|
|
||||||
compiler.launch_tool('v' + command, command)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// v run, v doc, etc
|
|
||||||
if !command.starts_with('-') && !command.ends_with('.v') && !os.exists(command) {
|
|
||||||
v_command(command, args)
|
|
||||||
}
|
|
||||||
// Print the version and exit.
|
|
||||||
if '-v' in options || '--version' in options {
|
|
||||||
version_hash := compiler.vhash()
|
|
||||||
println('V $compiler.Version $version_hash')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
else if '-h' in options || '--help' in options {
|
|
||||||
println(compiler.help_text)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// No args? REPL
|
|
||||||
else if command == '' || (args.len == 2 && args[1] == '-') {
|
|
||||||
compiler.launch_tool('vrepl', '')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Construct the V object from command line arguments
|
|
||||||
mut v := compiler.new_v(args)
|
|
||||||
if v.pref.is_verbose {
|
|
||||||
println(args)
|
|
||||||
}
|
|
||||||
if command == 'run' {
|
|
||||||
// always recompile for now, too error prone to skip recompilation otherwise
|
|
||||||
// for example for -repl usage, especially when piping lines to v
|
|
||||||
v.compile()
|
|
||||||
v.run_compiled_executable_and_exit()
|
|
||||||
}
|
|
||||||
mut tmark := benchmark.new_benchmark()
|
|
||||||
if v.pref.x64 {
|
|
||||||
v.compile_x64()
|
|
||||||
}
|
|
||||||
else if v.pref.v2 {
|
|
||||||
v.compile2()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.compile()
|
|
||||||
}
|
|
||||||
if v.pref.is_stats {
|
|
||||||
tmark.stop()
|
|
||||||
println('compilation took: ' + tmark.total_duration().str() + 'ms')
|
|
||||||
}
|
|
||||||
if v.pref.is_test {
|
|
||||||
v.run_compiled_executable_and_exit()
|
|
||||||
}
|
|
||||||
v.finalize_compilation()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn v_command(command string, args []string) {
|
|
||||||
match command {
|
|
||||||
'', '.', 'run', 'build' {
|
|
||||||
// handled later in vlib/compiler/main.v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
'version' {
|
|
||||||
println('V $compiler.Version $compiler.vhash()')
|
|
||||||
}
|
|
||||||
'help' {
|
|
||||||
println(compiler.help_text)
|
|
||||||
}
|
|
||||||
'translate' {
|
|
||||||
println('Translating C to V will be available in V 0.3 (January)')
|
|
||||||
}
|
|
||||||
'search', 'install', 'update', 'remove' {
|
|
||||||
compiler.launch_tool('vpm', command)
|
|
||||||
}
|
|
||||||
'get' {
|
|
||||||
println('use `v install` to install modules from vpm.vlang.io ')
|
|
||||||
}
|
|
||||||
'symlink' {
|
|
||||||
compiler.create_symlink()
|
|
||||||
}
|
|
||||||
'runrepl' {
|
|
||||||
// TODO: remove this after 2020/02/01
|
|
||||||
eprintln('`v runrepl` has been deprecated. Please use `v repl` instead.')
|
|
||||||
compiler.launch_tool('vrepl', 'runrepl')
|
|
||||||
}
|
|
||||||
'doc' {
|
|
||||||
vexe := os.executable()
|
|
||||||
vdir := filepath.dir(os.executable())
|
|
||||||
os.chdir(vdir)
|
|
||||||
mod := args.last()
|
|
||||||
os.system('$vexe build module vlib$os.path_separator' + args.last())
|
|
||||||
vhfile := filepath.join(compiler.v_modules_path,'vlib','${mod}.vh')
|
|
||||||
txt := os.read_file(vhfile) or {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
println(txt)
|
|
||||||
// v.gen_doc_html_for_module(args.last())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
eprintln('v $command: unknown command\nRun "v help" for usage.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit(0)
|
|
||||||
}
|
|
|
@ -166,8 +166,8 @@ fn (v mut V) new_parser_from_file(path string) Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.compile_defines.len > 0 {
|
if v.pref.compile_defines.len > 0 {
|
||||||
for cdefine in v.compile_defines {
|
for cdefine in v.pref.compile_defines {
|
||||||
custom_path_ending := '_d_${cdefine}.v'
|
custom_path_ending := '_d_${cdefine}.v'
|
||||||
if path.ends_with(custom_path_ending){
|
if path.ends_with(custom_path_ending){
|
||||||
path_platform = custom_path_ending
|
path_platform = custom_path_ending
|
||||||
|
@ -215,8 +215,8 @@ fn (v mut V) new_parser(scanner &Scanner) Parser {
|
||||||
cgen: v.cgen
|
cgen: v.cgen
|
||||||
//x64: v.x64
|
//x64: v.x64
|
||||||
pref: v.pref
|
pref: v.pref
|
||||||
os: v.os
|
os: v.pref.os
|
||||||
vroot: v.vroot
|
vroot: v.pref.vroot
|
||||||
local_vars: [Var{
|
local_vars: [Var{
|
||||||
}].repeat(MaxLocalVars)
|
}].repeat(MaxLocalVars)
|
||||||
import_table: new_import_table()
|
import_table: new_import_table()
|
||||||
|
@ -443,7 +443,7 @@ fn (p mut Parser) parse(pass Pass) {
|
||||||
//
|
//
|
||||||
p.fgen_nl()
|
p.fgen_nl()
|
||||||
p.cgen.nogen = false
|
p.cgen.nogen = false
|
||||||
if p.pref.build_mode == .build_module && p.mod != p.v.mod {
|
if p.pref.build_mode == .build_module && p.mod != p.v.pref.mod {
|
||||||
// println('skipping $p.mod (v.mod = $p.v.mod)')
|
// println('skipping $p.mod (v.mod = $p.v.mod)')
|
||||||
p.cgen.nogen = true
|
p.cgen.nogen = true
|
||||||
// defer { p.cgen.nogen = false }
|
// defer { p.cgen.nogen = false }
|
||||||
|
@ -453,7 +453,7 @@ fn (p mut Parser) parse(pass Pass) {
|
||||||
p.can_chash = p.mod in ['gg2', 'ui', 'uiold', 'darwin', 'clipboard', 'webview'] // TODO tmp remove
|
p.can_chash = p.mod in ['gg2', 'ui', 'uiold', 'darwin', 'clipboard', 'webview'] // TODO tmp remove
|
||||||
// Import pass - the first and the smallest pass that only analyzes imports
|
// Import pass - the first and the smallest pass that only analyzes imports
|
||||||
// if we are a building module get the full module name from v.mod
|
// if we are a building module get the full module name from v.mod
|
||||||
fq_mod := if p.pref.build_mode == .build_module && p.v.mod.ends_with(p.mod) { p.v.mod }
|
fq_mod := if p.pref.build_mode == .build_module && p.v.pref.mod.ends_with(p.mod) { p.v.pref.mod }
|
||||||
// fully qualify the module name, eg base64 to encoding.base64
|
// fully qualify the module name, eg base64 to encoding.base64
|
||||||
else { p.table.qualify_module(p.mod, p.file_path) }
|
else { p.table.qualify_module(p.mod, p.file_path) }
|
||||||
p.table.register_module(fq_mod)
|
p.table.register_module(fq_mod)
|
||||||
|
|
|
@ -5,9 +5,9 @@ module compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
os
|
os
|
||||||
os.cmdline
|
|
||||||
time
|
time
|
||||||
filepath
|
filepath
|
||||||
|
v.pref
|
||||||
)
|
)
|
||||||
|
|
||||||
fn todo() {
|
fn todo() {
|
||||||
|
@ -34,8 +34,8 @@ fn (v mut V) cc() {
|
||||||
vdir := filepath.dir(vexe)
|
vdir := filepath.dir(vexe)
|
||||||
// Just create a C/JavaScript file and exit
|
// Just create a C/JavaScript file and exit
|
||||||
// for example: `v -o v.c compiler`
|
// for example: `v -o v.c compiler`
|
||||||
ends_with_c := v.out_name.ends_with('.c')
|
ends_with_c := v.pref.out_name.ends_with('.c')
|
||||||
ends_with_js := v.out_name.ends_with('.js')
|
ends_with_js := v.pref.out_name.ends_with('.js')
|
||||||
|
|
||||||
if v.pref.is_pretty_c && !ends_with_js {
|
if v.pref.is_pretty_c && !ends_with_js {
|
||||||
format_result := os.exec('clang-format -i -style=file "$v.out_name_c"') or {
|
format_result := os.exec('clang-format -i -style=file "$v.out_name_c"') or {
|
||||||
|
@ -59,7 +59,7 @@ fn (v mut V) cc() {
|
||||||
println('V.js compiler not found, building...')
|
println('V.js compiler not found, building...')
|
||||||
// Build V.js. Specifying `-os js` makes V include
|
// Build V.js. Specifying `-os js` makes V include
|
||||||
// only _js.v files and ignore _c.v files.
|
// only _js.v files and ignore _c.v files.
|
||||||
ret := os.system('$vexe -o $vjs_path -os js $vdir/v.v')
|
ret := os.system('$vexe -o $vjs_path -os js $vdir/cmd/v')
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
println('Done.')
|
println('Done.')
|
||||||
}
|
}
|
||||||
|
@ -68,21 +68,21 @@ fn (v mut V) cc() {
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret := os.system('$vjs_path -o $v.out_name $v.dir')
|
ret := os.system('$vjs_path -o $v.pref.out_name $v.pref.path')
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
println('Done. Run it with `node $v.out_name`')
|
println('Done. Run it with `node $v.pref.out_name`')
|
||||||
println('JS backend is at a very early stage.')
|
println('JS backend is at a very early stage.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// v.out_name_c may be on a different partition than v.out_name
|
// v.out_name_c may be on a different partition than v.out_name
|
||||||
os.mv_by_cp(v.out_name_c, v.out_name)or{
|
os.mv_by_cp(v.out_name_c, v.pref.out_name)or{
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
// Cross compiling for Windows
|
// Cross compiling for Windows
|
||||||
if v.os == .windows {
|
if v.pref.os == .windows {
|
||||||
$if !windows {
|
$if !windows {
|
||||||
v.cc_windows_cross()
|
v.cc_windows_cross()
|
||||||
return
|
return
|
||||||
|
@ -136,29 +136,29 @@ fn (v mut V) cc() {
|
||||||
if !v.pref.is_so
|
if !v.pref.is_so
|
||||||
&& v.pref.build_mode != .build_module
|
&& v.pref.build_mode != .build_module
|
||||||
&& os.user_os() == 'windows'
|
&& os.user_os() == 'windows'
|
||||||
&& !v.out_name.ends_with('.exe')
|
&& !v.pref.out_name.ends_with('.exe')
|
||||||
{
|
{
|
||||||
v.out_name += '.exe'
|
v.pref.out_name += '.exe'
|
||||||
}
|
}
|
||||||
|
|
||||||
// linux_host := os.user_os() == 'linux'
|
// linux_host := os.user_os() == 'linux'
|
||||||
v.log('cc() isprod=$v.pref.is_prod outname=$v.out_name')
|
v.log('cc() isprod=$v.pref.is_prod outname=$v.pref.out_name')
|
||||||
if v.pref.is_so {
|
if v.pref.is_so {
|
||||||
a << '-shared -fPIC ' // -Wl,-z,defs'
|
a << '-shared -fPIC ' // -Wl,-z,defs'
|
||||||
v.out_name = v.out_name + '.so'
|
v.pref.out_name += '.so'
|
||||||
}
|
}
|
||||||
if v.pref.is_bare {
|
if v.pref.is_bare {
|
||||||
a << '-fno-stack-protector -static -ffreestanding -nostdlib'
|
a << '-fno-stack-protector -static -ffreestanding -nostdlib'
|
||||||
}
|
}
|
||||||
if v.pref.build_mode == .build_module {
|
if v.pref.build_mode == .build_module {
|
||||||
// Create the modules & out directory if it's not there.
|
// Create the modules & out directory if it's not there.
|
||||||
mut out_dir := if v.dir.starts_with('vlib') { '$v_modules_path${os.path_separator}cache${os.path_separator}$v.dir' } else { '$v_modules_path${os.path_separator}$v.dir' }
|
mut out_dir := if v.pref.path.starts_with('vlib') { '$v_modules_path${os.path_separator}cache${os.path_separator}$v.pref.path' } else { '$v_modules_path${os.path_separator}$v.pref.path' }
|
||||||
pdir := out_dir.all_before_last(os.path_separator)
|
pdir := out_dir.all_before_last(os.path_separator)
|
||||||
if !os.is_dir(pdir) {
|
if !os.is_dir(pdir) {
|
||||||
os.mkdir_all(pdir)
|
os.mkdir_all(pdir)
|
||||||
}
|
}
|
||||||
v.out_name = '${out_dir}.o' // v.out_name
|
v.pref.out_name = '${out_dir}.o' // v.out_name
|
||||||
println('Building ${v.out_name}...')
|
println('Building ${v.pref.out_name}...')
|
||||||
}
|
}
|
||||||
debug_mode := v.pref.is_debug
|
debug_mode := v.pref.is_debug
|
||||||
mut debug_options := '-g'
|
mut debug_options := '-g'
|
||||||
|
@ -198,7 +198,7 @@ fn (v mut V) cc() {
|
||||||
if debug_mode && os.user_os() != 'windows' {
|
if debug_mode && os.user_os() != 'windows' {
|
||||||
a << ' -rdynamic ' // needed for nicer symbolic backtraces
|
a << ' -rdynamic ' // needed for nicer symbolic backtraces
|
||||||
}
|
}
|
||||||
if v.pref.ccompiler != 'msvc' && v.os != .freebsd {
|
if v.pref.ccompiler != 'msvc' && v.pref.os != .freebsd {
|
||||||
a << '-Werror=implicit-function-declaration'
|
a << '-Werror=implicit-function-declaration'
|
||||||
}
|
}
|
||||||
for f in v.generate_hotcode_reloading_compiler_flags() {
|
for f in v.generate_hotcode_reloading_compiler_flags() {
|
||||||
|
@ -269,24 +269,24 @@ fn (v mut V) cc() {
|
||||||
// Cross compiling windows
|
// Cross compiling windows
|
||||||
//
|
//
|
||||||
// Output executable name
|
// Output executable name
|
||||||
a << '-o "$v.out_name"'
|
a << '-o "$v.pref.out_name"'
|
||||||
if os.is_dir(v.out_name) {
|
if os.is_dir(v.pref.out_name) {
|
||||||
verror("\'$v.out_name\' is a directory")
|
verror("\'$v.pref.out_name\' is a directory")
|
||||||
}
|
}
|
||||||
// macOS code can include objective C TODO remove once objective C is replaced with C
|
// macOS code can include objective C TODO remove once objective C is replaced with C
|
||||||
if v.os == .mac {
|
if v.pref.os == .mac {
|
||||||
a << '-x objective-c'
|
a << '-x objective-c'
|
||||||
}
|
}
|
||||||
// The C file we are compiling
|
// The C file we are compiling
|
||||||
a << '"$v.out_name_c"'
|
a << '"$v.out_name_c"'
|
||||||
if v.os == .mac {
|
if v.pref.os == .mac {
|
||||||
a << '-x none'
|
a << '-x none'
|
||||||
}
|
}
|
||||||
// Min macos version is mandatory I think?
|
// Min macos version is mandatory I think?
|
||||||
if v.os == .mac {
|
if v.pref.os == .mac {
|
||||||
a << '-mmacosx-version-min=10.7'
|
a << '-mmacosx-version-min=10.7'
|
||||||
}
|
}
|
||||||
if v.os == .windows {
|
if v.pref.os == .windows {
|
||||||
a << '-municode'
|
a << '-municode'
|
||||||
}
|
}
|
||||||
cflags := v.get_os_cflags()
|
cflags := v.get_os_cflags()
|
||||||
|
@ -297,18 +297,18 @@ fn (v mut V) cc() {
|
||||||
a << libs
|
a << libs
|
||||||
// Without these libs compilation will fail on Linux
|
// Without these libs compilation will fail on Linux
|
||||||
// || os.user_os() == 'linux'
|
// || os.user_os() == 'linux'
|
||||||
if !v.pref.is_bare && v.pref.build_mode != .build_module && v.os in [.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku] {
|
if !v.pref.is_bare && v.pref.build_mode != .build_module && v.pref.os in [.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku] {
|
||||||
a << '-lm -lpthread '
|
a << '-lm -lpthread '
|
||||||
// -ldl is a Linux only thing. BSDs have it in libc.
|
// -ldl is a Linux only thing. BSDs have it in libc.
|
||||||
if v.os == .linux {
|
if v.pref.os == .linux {
|
||||||
a << ' -ldl '
|
a << ' -ldl '
|
||||||
}
|
}
|
||||||
if v.os == .freebsd {
|
if v.pref.os == .freebsd {
|
||||||
// FreeBSD: backtrace needs execinfo library while linking
|
// FreeBSD: backtrace needs execinfo library while linking
|
||||||
a << ' -lexecinfo '
|
a << ' -lexecinfo '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !v.pref.is_bare && v.os == .js && os.user_os() == 'linux' {
|
if !v.pref.is_bare && v.pref.os == .js && os.user_os() == 'linux' {
|
||||||
a << '-lm'
|
a << '-lm'
|
||||||
}
|
}
|
||||||
args := a.join(' ')
|
args := a.join(' ')
|
||||||
|
@ -351,6 +351,18 @@ start:
|
||||||
}
|
}
|
||||||
if v.pref.is_debug {
|
if v.pref.is_debug {
|
||||||
println(res.output)
|
println(res.output)
|
||||||
|
verror("
|
||||||
|
==================
|
||||||
|
C error. This should never happen.
|
||||||
|
|
||||||
|
V compiler version: V $Version $vhash()
|
||||||
|
Host OS: ${pref.get_host_os().str()}
|
||||||
|
Target OS: $v.pref.os.str()
|
||||||
|
|
||||||
|
If you were not working with C interop and are not sure about what's happening,
|
||||||
|
please put the whole output in a pastebin and contact us through the following ways with a link to the pastebin:
|
||||||
|
- Raise an issue on GitHub: https://github.com/vlang/v/issues/new/choose
|
||||||
|
- Ask a question in #help on Discord: https://discord.gg/vlang")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if res.output.len < 30 {
|
if res.output.len < 30 {
|
||||||
|
@ -359,11 +371,19 @@ start:
|
||||||
q := res.output.all_after('error: ').limit(150)
|
q := res.output.all_after('error: ').limit(150)
|
||||||
println('==================')
|
println('==================')
|
||||||
println(q)
|
println(q)
|
||||||
|
println('...')
|
||||||
println('==================')
|
println('==================')
|
||||||
println('...\n(Use `v -cg` to print the entire error message)\n')
|
println('(Use `v -cg` to print the entire error message)\n')
|
||||||
}
|
}
|
||||||
|
verror("C error.
|
||||||
|
|
||||||
|
Please make sure that:
|
||||||
|
- You have all V dependencies installed.
|
||||||
|
- You did not declare a C function that was not included. (Try commenting your code that involves C interop)
|
||||||
|
- You are running the latest version of V. (Try running `v up` and rerunning your command)
|
||||||
|
|
||||||
|
If you're confident that all of the above is true, please try running V with the `-cg` option which enables more debugging capabilities.\n")
|
||||||
}
|
}
|
||||||
verror('C error. This should never happen. ' + '\nPlease create a GitHub issue: https://github.com/vlang/v/issues/new/choose')
|
|
||||||
}
|
}
|
||||||
diff := time.ticks() - ticks
|
diff := time.ticks() - ticks
|
||||||
// Print the C command
|
// Print the C command
|
||||||
|
@ -402,16 +422,16 @@ start:
|
||||||
println('-compress does not work on Windows for now')
|
println('-compress does not work on Windows for now')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret := os.system('strip $v.out_name')
|
ret := os.system('strip $v.pref.out_name')
|
||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
println('strip failed')
|
println('strip failed')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// NB: upx --lzma can sometimes fail with NotCompressibleException
|
// NB: upx --lzma can sometimes fail with NotCompressibleException
|
||||||
// See https://github.com/vlang/v/pull/3528
|
// See https://github.com/vlang/v/pull/3528
|
||||||
mut ret2 := os.system('upx --lzma -qqq $v.out_name')
|
mut ret2 := os.system('upx --lzma -qqq $v.pref.out_name')
|
||||||
if ret2 != 0 {
|
if ret2 != 0 {
|
||||||
ret2 = os.system('upx -qqq $v.out_name')
|
ret2 = os.system('upx -qqq $v.pref.out_name')
|
||||||
}
|
}
|
||||||
if ret2 != 0 {
|
if ret2 != 0 {
|
||||||
println('upx failed')
|
println('upx failed')
|
||||||
|
@ -430,10 +450,10 @@ start:
|
||||||
|
|
||||||
fn (c mut V) cc_windows_cross() {
|
fn (c mut V) cc_windows_cross() {
|
||||||
println('Cross compiling for Windows...')
|
println('Cross compiling for Windows...')
|
||||||
if !c.out_name.ends_with('.exe') {
|
if !c.pref.out_name.ends_with('.exe') {
|
||||||
c.out_name = c.out_name + '.exe'
|
c.pref.out_name += '.exe'
|
||||||
}
|
}
|
||||||
mut args := '-o $c.out_name -w -L. '
|
mut args := '-o $c.pref.out_name -w -L. '
|
||||||
cflags := c.get_os_cflags()
|
cflags := c.get_os_cflags()
|
||||||
// -I flags
|
// -I flags
|
||||||
args += if c.pref.ccompiler == 'msvc' { cflags.c_options_before_target_msvc() } else { cflags.c_options_before_target() }
|
args += if c.pref.ccompiler == 'msvc' { cflags.c_options_before_target_msvc() } else { cflags.c_options_before_target() }
|
||||||
|
@ -509,65 +529,12 @@ fn (c &V) build_thirdparty_obj_files() {
|
||||||
build_thirdparty_obj_file_with_msvc(flag.value, rest_of_module_flags)
|
build_thirdparty_obj_file_with_msvc(flag.value, rest_of_module_flags)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
build_thirdparty_obj_file(flag.value, rest_of_module_flags)
|
c.build_thirdparty_obj_file(flag.value, rest_of_module_flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_c_compiler() string {
|
|
||||||
args := env_vflags_and_os_args()
|
|
||||||
defaultcc := find_c_compiler_default()
|
|
||||||
return cmdline.option(args, '-cc', defaultcc)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_c_compiler_default() string {
|
|
||||||
// fast_clang := '/usr/local/Cellar/llvm/8.0.0/bin/clang'
|
|
||||||
// if os.exists(fast_clang) {
|
|
||||||
// return fast_clang
|
|
||||||
// }
|
|
||||||
// TODO fix $if after 'string'
|
|
||||||
$if windows {
|
|
||||||
return 'gcc'
|
|
||||||
}
|
|
||||||
return 'cc'
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_c_compiler_thirdparty_options() string {
|
|
||||||
fullargs := env_vflags_and_os_args()
|
|
||||||
mut cflags := cmdline.many_values(fullargs,'-cflags')
|
|
||||||
$if !windows {
|
|
||||||
cflags << '-fPIC'
|
|
||||||
}
|
|
||||||
if '-m32' in fullargs {
|
|
||||||
cflags << '-m32'
|
|
||||||
}
|
|
||||||
return cflags.join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_defines(defines []string) ([]string,[]string) {
|
|
||||||
// '-d abc -d xyz=1 -d qwe=0' should produce:
|
|
||||||
// compile_defines: ['abc','xyz']
|
|
||||||
// compile_defines_all ['abc','xyz','qwe']
|
|
||||||
mut compile_defines := []string
|
|
||||||
mut compile_defines_all := []string
|
|
||||||
for dfn in defines {
|
|
||||||
dfn_parts := dfn.split('=')
|
|
||||||
if dfn_parts.len == 1 {
|
|
||||||
compile_defines << dfn
|
|
||||||
compile_defines_all << dfn
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if dfn_parts.len == 2 {
|
|
||||||
compile_defines_all << dfn_parts[0]
|
|
||||||
if dfn_parts[1] == '1' {
|
|
||||||
compile_defines << dfn_parts[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return compile_defines, compile_defines_all
|
|
||||||
}
|
|
||||||
|
|
||||||
fn missing_compiler_info() string {
|
fn missing_compiler_info() string {
|
||||||
$if windows {
|
$if windows {
|
||||||
return 'https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows'
|
return 'https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows'
|
||||||
|
|
|
@ -20,12 +20,12 @@ pub fn (c &CFlag) str() string {
|
||||||
fn (v &V) get_os_cflags() []CFlag {
|
fn (v &V) get_os_cflags() []CFlag {
|
||||||
mut flags := []CFlag
|
mut flags := []CFlag
|
||||||
mut ctimedefines := []string
|
mut ctimedefines := []string
|
||||||
if v.compile_defines.len > 0 {
|
if v.pref.compile_defines.len > 0 {
|
||||||
ctimedefines << v.compile_defines
|
ctimedefines << v.pref.compile_defines
|
||||||
}
|
}
|
||||||
|
|
||||||
for flag in v.table.cflags {
|
for flag in v.table.cflags {
|
||||||
if flag.os == '' || (flag.os == 'linux' && v.os == .linux) || (flag.os == 'darwin' && v.os == .mac) || (flag.os == 'freebsd' && v.os == .freebsd) || (flag.os == 'windows' && v.os == .windows) {
|
if flag.os == '' || (flag.os == 'linux' && v.pref.os == .linux) || (flag.os == 'darwin' && v.pref.os == .mac) || (flag.os == 'freebsd' && v.pref.os == .freebsd) || (flag.os == 'windows' && v.pref.os == .windows) {
|
||||||
flags << flag
|
flags << flag
|
||||||
}
|
}
|
||||||
if flag.os in ctimedefines {
|
if flag.os in ctimedefines {
|
||||||
|
|
|
@ -43,7 +43,7 @@ mut:
|
||||||
cut_pos int
|
cut_pos int
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_cgen(out_name_c string) &CGen {
|
pub fn new_cgen(out_name_c string) &CGen {
|
||||||
path := out_name_c
|
path := out_name_c
|
||||||
out := os.create(path)or{
|
out := os.create(path)or{
|
||||||
println('failed to create $path')
|
println('failed to create $path')
|
||||||
|
@ -272,7 +272,7 @@ fn (g mut CGen) add_to_main(s string) {
|
||||||
g.fn_main = g.fn_main + s
|
g.fn_main = g.fn_main + s
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_thirdparty_obj_file(path string, moduleflags []CFlag) {
|
fn (v &V) build_thirdparty_obj_file(path string, moduleflags []CFlag) {
|
||||||
obj_path := os.realpath(path)
|
obj_path := os.realpath(path)
|
||||||
if os.exists(obj_path) {
|
if os.exists(obj_path) {
|
||||||
return
|
return
|
||||||
|
@ -288,11 +288,9 @@ fn build_thirdparty_obj_file(path string, moduleflags []CFlag) {
|
||||||
cfiles += '"' + os.realpath(parent + os.path_separator + file) + '" '
|
cfiles += '"' + os.realpath(parent + os.path_separator + file) + '" '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cc := find_c_compiler()
|
|
||||||
cc_thirdparty_options := find_c_compiler_thirdparty_options()
|
|
||||||
btarget := moduleflags.c_options_before_target()
|
btarget := moduleflags.c_options_before_target()
|
||||||
atarget := moduleflags.c_options_after_target()
|
atarget := moduleflags.c_options_after_target()
|
||||||
cmd := '$cc $cc_thirdparty_options $btarget -c -o "$obj_path" $cfiles $atarget '
|
cmd := '$v.pref.ccompiler $v.pref.third_party_option $btarget -c -o "$obj_path" $cfiles $atarget '
|
||||||
res := os.exec(cmd)or{
|
res := os.exec(cmd)or{
|
||||||
println('failed thirdparty object build cmd: $cmd')
|
println('failed thirdparty object build cmd: $cmd')
|
||||||
verror(err)
|
verror(err)
|
||||||
|
|
|
@ -112,7 +112,7 @@ fn (p mut Parser) comp_time() {
|
||||||
else if name == 'clang' {
|
else if name == 'clang' {
|
||||||
p.comptime_if_block('__clang__', not)
|
p.comptime_if_block('__clang__', not)
|
||||||
}
|
}
|
||||||
else if p.v.compile_defines_all.len > 0 && name in p.v.compile_defines_all {
|
else if p.v.pref.compile_defines_all.len > 0 && name in p.v.pref.compile_defines_all {
|
||||||
// Support for *optional* custom compile defines, i.e.:
|
// Support for *optional* custom compile defines, i.e.:
|
||||||
//
|
//
|
||||||
// `[if custom]` => custom should be defined
|
// `[if custom]` => custom should be defined
|
||||||
|
@ -249,7 +249,7 @@ fn (p mut Parser) chash() {
|
||||||
flag = flag.replace('@VLIB_PATH', p.pref.vlib_path)
|
flag = flag.replace('@VLIB_PATH', p.pref.vlib_path)
|
||||||
flag = flag.replace('@VMOD', v_modules_path)
|
flag = flag.replace('@VMOD', v_modules_path)
|
||||||
// p.log('adding flag "$flag"')
|
// p.log('adding flag "$flag"')
|
||||||
_ = p.table.parse_cflag(flag, p.mod, p.v.compile_defines_all ) or {
|
_ = 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)
|
p.error_with_token_index(err, p.cur_tok_index() - 1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,7 +510,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.first_pass() && p.attr == 'live' && !(is_live || is_solive) {
|
if p.first_pass() && p.attr == 'live' && !(is_live || is_solive) {
|
||||||
println('INFO: run `v -live $p.v.dir `, if you want to use [live] function $f.name .')
|
println('INFO: run `v -live $p.v.pref.path `, if you want to use [live] function $f.name .')
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.is_vh || p.first_pass() || is_live || is_fn_header || skip_main_in_test {
|
if p.is_vh || p.first_pass() || is_live || is_fn_header || skip_main_in_test {
|
||||||
|
@ -774,7 +774,7 @@ fn (p mut Parser) verify_fn_before_call(f &Fn) {
|
||||||
// p.tok == fn_name
|
// p.tok == fn_name
|
||||||
fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type string) {
|
fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type string) {
|
||||||
p.verify_fn_before_call(f)
|
p.verify_fn_before_call(f)
|
||||||
is_comptime_define := f.comptime_define != '' && !(f.comptime_define in p.v.compile_defines )
|
is_comptime_define := f.comptime_define != '' && !(f.comptime_define in p.v.pref.compile_defines )
|
||||||
if is_comptime_define {
|
if is_comptime_define {
|
||||||
p.cgen.nogen = true
|
p.cgen.nogen = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ fn (v &V) generate_hotcode_reloading_compiler_flags() []string {
|
||||||
mut a := []string
|
mut a := []string
|
||||||
if v.pref.is_live || v.pref.is_so {
|
if v.pref.is_live || v.pref.is_so {
|
||||||
// See 'man dlopen', and test running a GUI program compiled with -live
|
// See 'man dlopen', and test running a GUI program compiled with -live
|
||||||
if (v.os == .linux || os.user_os() == 'linux') {
|
if (v.pref.os == .linux || os.user_os() == 'linux') {
|
||||||
a << '-rdynamic'
|
a << '-rdynamic'
|
||||||
}
|
}
|
||||||
if (v.os == .mac || os.user_os() == 'mac') {
|
if (v.pref.os == .mac || os.user_os() == 'mac') {
|
||||||
a << '-flat_namespace'
|
a << '-flat_namespace'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ fn (v &V) generate_hotcode_reloading_compiler_flags() []string {
|
||||||
|
|
||||||
fn (v &V) generate_hotcode_reloading_declarations() {
|
fn (v &V) generate_hotcode_reloading_declarations() {
|
||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
||||||
if v.os != .windows {
|
if v.pref.os != .windows {
|
||||||
if v.pref.is_so {
|
if v.pref.is_so {
|
||||||
cgen.genln('pthread_mutex_t live_fn_mutex;')
|
cgen.genln('pthread_mutex_t live_fn_mutex;')
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,8 @@ fn (v &V) generate_hotcode_reloading_main_caller() {
|
||||||
// We are in live code reload mode, so start the .so loader in the background
|
// We are in live code reload mode, so start the .so loader in the background
|
||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
||||||
cgen.genln('')
|
cgen.genln('')
|
||||||
file_base := filepath.filename(v.dir).replace('.v', '')
|
file_base := filepath.filename(v.pref.path).replace('.v', '')
|
||||||
if v.os != .windows {
|
if v.pref.os != .windows {
|
||||||
// unix:
|
// unix:
|
||||||
so_name := file_base + '.so'
|
so_name := file_base + '.so'
|
||||||
cgen.genln(' char *live_library_name = "$so_name";')
|
cgen.genln(' char *live_library_name = "$so_name";')
|
||||||
|
@ -79,7 +79,7 @@ fn (v &V) generate_hot_reload_code() {
|
||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
||||||
// Hot code reloading
|
// Hot code reloading
|
||||||
if v.pref.is_live {
|
if v.pref.is_live {
|
||||||
mut file := os.realpath(v.dir)
|
mut file := os.realpath(v.pref.path)
|
||||||
file_base := filepath.filename(file).replace('.v', '')
|
file_base := filepath.filename(file).replace('.v', '')
|
||||||
so_name := file_base + '.so'
|
so_name := file_base + '.so'
|
||||||
// Need to build .so file before building the live application
|
// Need to build .so file before building the live application
|
||||||
|
@ -115,7 +115,7 @@ void lfnmutex_print(char *s){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
')
|
')
|
||||||
if v.os != .windows {
|
if v.pref.os != .windows {
|
||||||
cgen.genln('
|
cgen.genln('
|
||||||
void* live_lib=0;
|
void* live_lib=0;
|
||||||
int load_so(byteptr path) {
|
int load_so(byteptr path) {
|
||||||
|
|
|
@ -5,7 +5,6 @@ module compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
os
|
os
|
||||||
os.cmdline
|
|
||||||
strings
|
strings
|
||||||
filepath
|
filepath
|
||||||
v.pref
|
v.pref
|
||||||
|
@ -35,21 +34,15 @@ enum Pass {
|
||||||
main
|
main
|
||||||
}
|
}
|
||||||
|
|
||||||
struct V {
|
pub struct V {
|
||||||
pub mut:
|
pub mut:
|
||||||
os pref.OS // the OS to build for
|
|
||||||
out_name_c string // name of the temporary C file
|
out_name_c string // name of the temporary C file
|
||||||
files []string // all V files that need to be parsed and compiled
|
files []string // all V files that need to be parsed and compiled
|
||||||
dir string // directory (or file) being compiled (TODO rename to path?)
|
|
||||||
compiled_dir string // contains os.realpath() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
|
compiled_dir string // contains os.realpath() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
|
||||||
table &Table // table with types, vars, functions etc
|
table &Table // table with types, vars, functions etc
|
||||||
cgen &CGen // C code generator
|
cgen &CGen // C code generator
|
||||||
//x64 &x64.Gen
|
//x64 &x64.Gen
|
||||||
pref &pref.Preferences // all the preferences and settings extracted to a struct for reusability
|
pref &pref.Preferences // all the preferences and settings extracted to a struct for reusability
|
||||||
lang_dir string // "~/code/v"
|
|
||||||
out_name string // "program.exe"
|
|
||||||
vroot string
|
|
||||||
mod string // module being built with -lib
|
|
||||||
parsers []Parser // file parsers
|
parsers []Parser // file parsers
|
||||||
vgen_buf strings.Builder // temporary buffer for generated V code (.str() etc)
|
vgen_buf strings.Builder // temporary buffer for generated V code (.str() etc)
|
||||||
file_parser_idx map[string]int // map absolute file path to v.parsers index
|
file_parser_idx map[string]int // map absolute file path to v.parsers index
|
||||||
|
@ -57,15 +50,33 @@ pub mut:
|
||||||
cached_mods []string
|
cached_mods []string
|
||||||
module_lookup_paths []string
|
module_lookup_paths []string
|
||||||
|
|
||||||
// -d vfmt and -d another=0 for `$if vfmt { will execute }` and `$if another { will NOT get here }`
|
v_fmt_all bool // << input set by cmd/tools/vfmt.v
|
||||||
compile_defines []string // just ['vfmt']
|
v_fmt_file string // << file given by the user from cmd/tools/vfmt.v
|
||||||
compile_defines_all []string // contains both: ['vfmt','another']
|
|
||||||
|
|
||||||
v_fmt_all bool // << input set by tools/vfmt.v
|
|
||||||
v_fmt_file string // << file given by the user from tools/vfmt.v
|
|
||||||
v_fmt_file_result string // >> file with formatted output generated by vlib/compiler/vfmt.v
|
v_fmt_file_result string // >> file with formatted output generated by vlib/compiler/vfmt.v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_v(pref &pref.Preferences) &V {
|
||||||
|
rdir := os.realpath(pref.path)
|
||||||
|
|
||||||
|
mut out_name_c := get_vtmp_filename(pref.out_name, '.tmp.c')
|
||||||
|
if pref.is_so {
|
||||||
|
out_name_c = get_vtmp_filename(pref.out_name, '.tmp.so.c')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut vgen_buf := strings.new_builder(1000)
|
||||||
|
vgen_buf.writeln('module vgen\nimport strings')
|
||||||
|
|
||||||
|
return &V{
|
||||||
|
compiled_dir: if os.is_dir(rdir) { rdir } else { filepath.dir(rdir) }
|
||||||
|
table: new_table(pref.obfuscate)
|
||||||
|
out_name_c: out_name_c
|
||||||
|
cgen: new_cgen(out_name_c)
|
||||||
|
//x64: x64.new_gen(out_name)
|
||||||
|
pref: pref
|
||||||
|
vgen_buf: vgen_buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Should be called by main at the end of the compilation process, to cleanup
|
// Should be called by main at the end of the compilation process, to cleanup
|
||||||
pub fn (v &V) finalize_compilation() {
|
pub fn (v &V) finalize_compilation() {
|
||||||
// TODO remove
|
// TODO remove
|
||||||
|
@ -166,7 +177,7 @@ pub fn (v mut V) compile() {
|
||||||
if v.pref.prealloc {
|
if v.pref.prealloc {
|
||||||
cgen.genln('#define VPREALLOC (1)')
|
cgen.genln('#define VPREALLOC (1)')
|
||||||
}
|
}
|
||||||
if v.os == .js {
|
if v.pref.os == .js {
|
||||||
cgen.genln('#define _VJS (1) ')
|
cgen.genln('#define _VJS (1) ')
|
||||||
}
|
}
|
||||||
v_hash := vhash()
|
v_hash := vhash()
|
||||||
|
@ -189,11 +200,11 @@ pub fn (v mut V) compile() {
|
||||||
cgen.genln('#include <stdint.h>')
|
cgen.genln('#include <stdint.h>')
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.compile_defines_all.len > 0 {
|
if v.pref.compile_defines_all.len > 0 {
|
||||||
cgen.genln('')
|
cgen.genln('')
|
||||||
cgen.genln('// All custom defines : ' + v.compile_defines_all.join(','))
|
cgen.genln('// All custom defines : ' + v.pref.compile_defines_all.join(','))
|
||||||
cgen.genln('// Turned ON custom defines: ' + v.compile_defines.join(','))
|
cgen.genln('// Turned ON custom defines: ' + v.pref.compile_defines.join(','))
|
||||||
for cdefine in v.compile_defines {
|
for cdefine in v.pref.compile_defines {
|
||||||
cgen.genln('#define CUSTOM_DEFINE_${cdefine}')
|
cgen.genln('#define CUSTOM_DEFINE_${cdefine}')
|
||||||
}
|
}
|
||||||
cgen.genln('//')
|
cgen.genln('//')
|
||||||
|
@ -234,7 +245,7 @@ pub fn (v mut V) compile() {
|
||||||
if '-debug_alloc' in os.args {
|
if '-debug_alloc' in os.args {
|
||||||
cgen.genln('#define DEBUG_ALLOC 1')
|
cgen.genln('#define DEBUG_ALLOC 1')
|
||||||
}
|
}
|
||||||
if v.pref.is_live && v.os != .windows {
|
if v.pref.is_live && v.pref.os != .windows {
|
||||||
cgen.includes << '#include <dlfcn.h>'
|
cgen.includes << '#include <dlfcn.h>'
|
||||||
}
|
}
|
||||||
// cgen.genln('/*================================== FNS =================================*/')
|
// cgen.genln('/*================================== FNS =================================*/')
|
||||||
|
@ -261,7 +272,7 @@ pub fn (v mut V) compile() {
|
||||||
vgen_parser.parse(.main)
|
vgen_parser.parse(.main)
|
||||||
// Generate .vh if we are building a module
|
// Generate .vh if we are building a module
|
||||||
if v.pref.build_mode == .build_module {
|
if v.pref.build_mode == .build_module {
|
||||||
generate_vh(v.dir)
|
generate_vh(v.pref.path)
|
||||||
}
|
}
|
||||||
// All definitions
|
// All definitions
|
||||||
mut def := strings.new_builder(10000) // Avoid unnecessary allocations
|
mut def := strings.new_builder(10000) // Avoid unnecessary allocations
|
||||||
|
@ -319,7 +330,7 @@ pub fn (v mut V) compile2() {
|
||||||
println(v.files)
|
println(v.files)
|
||||||
}
|
}
|
||||||
mut b := v.new_v2()
|
mut b := v.new_v2()
|
||||||
b.build_c(v.files, v.out_name)
|
b.build_c(v.files, v.pref.out_name)
|
||||||
v.cc()
|
v.cc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,18 +340,18 @@ pub fn (v mut V) compile_x64() {
|
||||||
println('You are not on a Linux system, so you will not ' + 'be able to run the resulting executable')
|
println('You are not on a Linux system, so you will not ' + 'be able to run the resulting executable')
|
||||||
}
|
}
|
||||||
//v.files << v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin','bare'))
|
//v.files << v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin','bare'))
|
||||||
v.files << v.dir
|
v.files << v.pref.path
|
||||||
v.set_module_lookup_paths()
|
v.set_module_lookup_paths()
|
||||||
mut b := v.new_v2()
|
mut b := v.new_v2()
|
||||||
// move all this logic to v2
|
// move all this logic to v2
|
||||||
b.build_x64(v.files, v.out_name)
|
b.build_x64(v.files, v.pref.out_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make v2 from v1
|
// make v2 from v1
|
||||||
fn (v &V) new_v2() builder.Builder {
|
fn (v &V) new_v2() builder.Builder {
|
||||||
mut b := builder.new_builder(v.pref)
|
mut b := builder.new_builder(v.pref)
|
||||||
b = { b|
|
b = { b|
|
||||||
os: v.os,
|
os: v.pref.os,
|
||||||
module_path: v_modules_path,
|
module_path: v_modules_path,
|
||||||
compiled_dir: v.compiled_dir,
|
compiled_dir: v.compiled_dir,
|
||||||
module_search_paths: v.module_lookup_paths
|
module_search_paths: v.module_lookup_paths
|
||||||
|
@ -356,7 +367,7 @@ fn (v mut V) generate_init() {
|
||||||
nogen := v.cgen.nogen
|
nogen := v.cgen.nogen
|
||||||
v.cgen.nogen = false
|
v.cgen.nogen = false
|
||||||
consts_init_body := v.cgen.consts_init.join_lines()
|
consts_init_body := v.cgen.consts_init.join_lines()
|
||||||
init_fn_name := mod_gen_name(v.mod) + '__init_consts'
|
init_fn_name := mod_gen_name(v.pref.mod) + '__init_consts'
|
||||||
v.cgen.genln('void ${init_fn_name}();\nvoid ${init_fn_name}() {\n$consts_init_body\n}')
|
v.cgen.genln('void ${init_fn_name}();\nvoid ${init_fn_name}() {\n$consts_init_body\n}')
|
||||||
v.cgen.nogen = nogen
|
v.cgen.nogen = nogen
|
||||||
}
|
}
|
||||||
|
@ -482,7 +493,7 @@ pub fn (v mut V) generate_main() {
|
||||||
// Generate a C `main`, which calls every single test function
|
// Generate a C `main`, which calls every single test function
|
||||||
v.gen_main_start(false)
|
v.gen_main_start(false)
|
||||||
if v.pref.is_stats {
|
if v.pref.is_stats {
|
||||||
cgen.genln('BenchedTests bt = main__start_testing(${test_fn_names.len},tos3("$v.dir"));')
|
cgen.genln('BenchedTests bt = main__start_testing(${test_fn_names.len},tos3("$v.pref.path"));')
|
||||||
}
|
}
|
||||||
for tfname in test_fn_names {
|
for tfname in test_fn_names {
|
||||||
if v.pref.is_stats {
|
if v.pref.is_stats {
|
||||||
|
@ -513,7 +524,7 @@ pub fn (v mut V) generate_main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (v mut V) gen_main_start(add_os_args bool) {
|
pub fn (v mut V) gen_main_start(add_os_args bool) {
|
||||||
if v.os == .windows {
|
if v.pref.os == .windows {
|
||||||
if 'glfw' in v.table.imports {
|
if 'glfw' in v.table.imports {
|
||||||
// GUI application
|
// GUI application
|
||||||
v.cgen.genln('int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, LPWSTR cmd_line, int show_cmd) { ')
|
v.cgen.genln('int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, LPWSTR cmd_line, int show_cmd) { ')
|
||||||
|
@ -531,7 +542,7 @@ pub fn (v mut V) gen_main_start(add_os_args bool) {
|
||||||
}
|
}
|
||||||
v.cgen.genln(' init();')
|
v.cgen.genln(' init();')
|
||||||
if add_os_args && 'os' in v.table.imports {
|
if add_os_args && 'os' in v.table.imports {
|
||||||
if v.os == .windows {
|
if v.pref.os == .windows {
|
||||||
v.cgen.genln(' os__args = os__init_os_args_wide(argc, argv);')
|
v.cgen.genln(' os__args = os__init_os_args_wide(argc, argv);')
|
||||||
} else {
|
} else {
|
||||||
v.cgen.genln(' os__args = os__init_os_args(argc, (byteptr*)argv);')
|
v.cgen.genln(' os__args = os__init_os_args(argc, (byteptr*)argv);')
|
||||||
|
@ -547,45 +558,12 @@ pub fn (v mut V) gen_main_end(return_statement string) {
|
||||||
v.cgen.genln('}')
|
v.cgen.genln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn final_target_out_name(out_name string) string {
|
|
||||||
$if windows {
|
|
||||||
return out_name.replace('/', '\\') + '.exe'
|
|
||||||
}
|
|
||||||
return if out_name.starts_with('/') { out_name } else { './' + out_name }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (v V) run_compiled_executable_and_exit() {
|
|
||||||
args := env_vflags_and_os_args()
|
|
||||||
if v.pref.is_verbose {
|
|
||||||
println('============ running $v.out_name ============')
|
|
||||||
}
|
|
||||||
mut cmd := '"' + final_target_out_name(v.out_name).replace('.exe', '') + '"'
|
|
||||||
args_after_no_options := cmdline.only_non_options( cmdline.after(args,['run','test']) )
|
|
||||||
if args_after_no_options.len > 1 {
|
|
||||||
cmd += ' ' + args_after_no_options[1..].join(' ')
|
|
||||||
}
|
|
||||||
if v.pref.is_test {
|
|
||||||
ret := os.system(cmd)
|
|
||||||
if ret != 0 {
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v.pref.is_run {
|
|
||||||
ret := os.system(cmd)
|
|
||||||
// TODO: make the runner wrapping as transparent as possible
|
|
||||||
// (i.e. use execve when implemented). For now though, the runner
|
|
||||||
// just returns the same exit code as the child process.
|
|
||||||
exit(ret)
|
|
||||||
}
|
|
||||||
exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (v &V) v_files_from_dir(dir string) []string {
|
pub fn (v &V) v_files_from_dir(dir string) []string {
|
||||||
mut res := []string
|
mut res := []string
|
||||||
if !os.exists(dir) {
|
if !os.exists(dir) {
|
||||||
if dir == 'compiler' && os.is_dir('vlib') {
|
if dir == 'compiler' && os.is_dir('vlib') {
|
||||||
println('looks like you are trying to build V with an old command')
|
println('looks like you are trying to build V with an old command')
|
||||||
println('use `v -o v v.v` instead of `v -o v compiler`')
|
println('use `v -o v cmd/v` instead of `v -o v compiler`')
|
||||||
}
|
}
|
||||||
verror("$dir doesn't exist")
|
verror("$dir doesn't exist")
|
||||||
}
|
}
|
||||||
|
@ -606,27 +584,27 @@ pub fn (v &V) v_files_from_dir(dir string) []string {
|
||||||
if file.ends_with('_test.v') {
|
if file.ends_with('_test.v') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (file.ends_with('_win.v') || file.ends_with('_windows.v')) && v.os != .windows {
|
if (file.ends_with('_win.v') || file.ends_with('_windows.v')) && v.pref.os != .windows {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (file.ends_with('_lin.v') || file.ends_with('_linux.v')) && v.os != .linux {
|
if (file.ends_with('_lin.v') || file.ends_with('_linux.v')) && v.pref.os != .linux {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (file.ends_with('_mac.v') || file.ends_with('_darwin.v')) && v.os != .mac {
|
if (file.ends_with('_mac.v') || file.ends_with('_darwin.v')) && v.pref.os != .mac {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if file.ends_with('_nix.v') && v.os == .windows {
|
if file.ends_with('_nix.v') && v.pref.os == .windows {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if file.ends_with('_js.v') && v.os != .js {
|
if file.ends_with('_js.v') && v.pref.os != .js {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if file.ends_with('_c.v') && v.os == .js {
|
if file.ends_with('_c.v') && v.pref.os == .js {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if v.compile_defines_all.len > 0 && file.contains('_d_') {
|
if v.pref.compile_defines_all.len > 0 && file.contains('_d_') {
|
||||||
mut allowed := false
|
mut allowed := false
|
||||||
for cdefine in v.compile_defines {
|
for cdefine in v.pref.compile_defines {
|
||||||
file_postfix := '_d_${cdefine}.v'
|
file_postfix := '_d_${cdefine}.v'
|
||||||
if file.ends_with(file_postfix) {
|
if file.ends_with(file_postfix) {
|
||||||
allowed = true
|
allowed = true
|
||||||
|
@ -740,15 +718,15 @@ pub fn (v &V) get_builtin_files() []string {
|
||||||
|
|
||||||
// get user files
|
// get user files
|
||||||
pub fn (v &V) get_user_files() []string {
|
pub fn (v &V) get_user_files() []string {
|
||||||
mut dir := v.dir
|
mut dir := v.pref.path
|
||||||
v.log('get_v_files($dir)')
|
v.log('get_v_files($dir)')
|
||||||
// Need to store user files separately, because they have to be added after
|
// Need to store user files separately, because they have to be added after
|
||||||
// libs, but we dont know which libs need to be added yet
|
// libs, but we dont know which libs need to be added yet
|
||||||
mut user_files := []string
|
mut user_files := []string
|
||||||
|
|
||||||
// See tools/preludes/README.md for more info about what preludes are
|
// See cmd/tools/preludes/README.md for more info about what preludes are
|
||||||
vroot := filepath.dir(vexe_path())
|
vroot := filepath.dir(vexe_path())
|
||||||
preludes_path := filepath.join(vroot,'tools','preludes')
|
preludes_path := filepath.join(vroot,'cmd','tools','preludes')
|
||||||
if v.pref.is_live {
|
if v.pref.is_live {
|
||||||
user_files << filepath.join(preludes_path,'live_main.v')
|
user_files << filepath.join(preludes_path,'live_main.v')
|
||||||
}
|
}
|
||||||
|
@ -858,284 +836,6 @@ pub fn (v &V) log(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_v(args []string) &V {
|
|
||||||
// Create modules dirs if they are missing
|
|
||||||
if !os.is_dir(v_modules_path) {
|
|
||||||
os.mkdir(v_modules_path)or{
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
os.mkdir('$v_modules_path${os.path_separator}cache')or{
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// optional, custom modules search path
|
|
||||||
user_mod_path := cmdline.option(args, '-user_mod_path', '')
|
|
||||||
// Location of all vlib files
|
|
||||||
vroot := filepath.dir(vexe_path())
|
|
||||||
vlib_path := cmdline.option(args, '-vlib-path', filepath.join(vroot,'vlib'))
|
|
||||||
vpath := cmdline.option(args, '-vpath', v_modules_path)
|
|
||||||
mut vgen_buf := strings.new_builder(1000)
|
|
||||||
vgen_buf.writeln('module vgen\nimport strings')
|
|
||||||
target_os := cmdline.option(args, '-os', '')
|
|
||||||
mut out_name := cmdline.option(args, '-o', 'a.out')
|
|
||||||
mut dir := args.last()
|
|
||||||
if 'run' in args {
|
|
||||||
args_after_run := cmdline.only_non_options( cmdline.after(args,['run']) )
|
|
||||||
dir = if args_after_run.len>0 { args_after_run[0] } else { '' }
|
|
||||||
}
|
|
||||||
if dir.ends_with(os.path_separator) {
|
|
||||||
dir = dir.all_before_last(os.path_separator)
|
|
||||||
}
|
|
||||||
if dir.starts_with('.$os.path_separator') {
|
|
||||||
dir = dir[2..]
|
|
||||||
}
|
|
||||||
if args.len < 2 {
|
|
||||||
dir = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// build mode
|
|
||||||
mut build_mode := pref.BuildMode.default_mode
|
|
||||||
mut mod := ''
|
|
||||||
joined_args := args.join(' ')
|
|
||||||
if joined_args.contains('build module ') {
|
|
||||||
build_mode = .build_module
|
|
||||||
os.chdir(vroot)
|
|
||||||
// v build module ~/v/os => os.o
|
|
||||||
mod_path := if dir.contains('vlib') { dir.all_after('vlib' + os.path_separator) } else if dir.starts_with('.\\') || dir.starts_with('./') { dir[2..] } else if dir.starts_with(os.path_separator) { dir.all_after(os.path_separator) } else { dir }
|
|
||||||
mod = mod_path.replace(os.path_separator, '.')
|
|
||||||
println('Building module "${mod}" (dir="$dir")...')
|
|
||||||
// out_name = '$TmpPath/vlib/${base}.o'
|
|
||||||
if !out_name.ends_with('.c') {
|
|
||||||
out_name = mod
|
|
||||||
}
|
|
||||||
// Cross compiling? Use separate dirs for each os
|
|
||||||
/*
|
|
||||||
if target_os != os.user_os() {
|
|
||||||
os.mkdir('$TmpPath/vlib/$target_os') or { panic(err) }
|
|
||||||
out_name = '$TmpPath/vlib/$target_os/${base}.o'
|
|
||||||
println('target_os=$target_os user_os=${os.user_os()}')
|
|
||||||
println('!Cross compiling $out_name')
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
is_test := dir.ends_with('_test.v')
|
|
||||||
is_script := dir.ends_with('.v') || dir.ends_with('.vsh')
|
|
||||||
if is_script && !os.exists(dir) {
|
|
||||||
println('`$dir` does not exist')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
// No -o provided? foo.v => foo
|
|
||||||
if out_name == 'a.out' && dir.ends_with('.v') && dir != '.v' {
|
|
||||||
out_name = dir[..dir.len - 2]
|
|
||||||
// Building V? Use v2, since we can't overwrite a running
|
|
||||||
// executable on Windows + the precompiled V is more
|
|
||||||
// optimized.
|
|
||||||
if out_name == 'v' && os.is_dir('vlib/compiler') {
|
|
||||||
println('Saving the resulting V executable in `./v2`')
|
|
||||||
println('Use `v -o v v.v` if you want to replace current ' + 'V executable.')
|
|
||||||
out_name = 'v2'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if we are in `/foo` and run `v .`, the executable should be `foo`
|
|
||||||
if dir == '.' && out_name == 'a.out' {
|
|
||||||
base := os.getwd().all_after(os.path_separator)
|
|
||||||
out_name = base.trim_space()
|
|
||||||
}
|
|
||||||
// `v -o dir/exec`, create "dir/" if it doesn't exist
|
|
||||||
if out_name.contains(os.path_separator) {
|
|
||||||
d := out_name.all_before_last(os.path_separator)
|
|
||||||
if !os.is_dir(d) {
|
|
||||||
println('creating a new directory "$d"')
|
|
||||||
os.mkdir(d)or{
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mut _os := pref.OS.mac
|
|
||||||
// No OS specifed? Use current system
|
|
||||||
if target_os == '' {
|
|
||||||
$if linux {
|
|
||||||
_os = .linux
|
|
||||||
}
|
|
||||||
$if macos {
|
|
||||||
_os = .mac
|
|
||||||
}
|
|
||||||
$if windows {
|
|
||||||
_os = .windows
|
|
||||||
}
|
|
||||||
$if freebsd {
|
|
||||||
_os = .freebsd
|
|
||||||
}
|
|
||||||
$if openbsd {
|
|
||||||
_os = .openbsd
|
|
||||||
}
|
|
||||||
$if netbsd {
|
|
||||||
_os = .netbsd
|
|
||||||
}
|
|
||||||
$if dragonfly {
|
|
||||||
_os = .dragonfly
|
|
||||||
}
|
|
||||||
$if solaris {
|
|
||||||
_os = .solaris
|
|
||||||
}
|
|
||||||
$if haiku {
|
|
||||||
_os = .haiku
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_os = os_from_string(target_os)
|
|
||||||
}
|
|
||||||
// println('VROOT=$vroot')
|
|
||||||
// v.exe's parent directory should contain vlib
|
|
||||||
if !os.is_dir(vlib_path) || !os.is_dir(vlib_path + os.path_separator + 'builtin') {
|
|
||||||
// println('vlib not found, downloading it...')
|
|
||||||
/*
|
|
||||||
ret := os.system('git clone --depth=1 https://github.com/vlang/v .')
|
|
||||||
if ret != 0 {
|
|
||||||
println('failed to `git clone` vlib')
|
|
||||||
println('make sure you are online and have git installed')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
println('vlib not found. It should be next to the V executable.')
|
|
||||||
println('Go to https://vlang.io to install V.')
|
|
||||||
println('(os.executable=${os.executable()} vlib_path=$vlib_path vexe_path=${vexe_path()}')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
mut out_name_c := get_vtmp_filename(out_name, '.tmp.c')
|
|
||||||
cflags := cmdline.many_values(args, '-cflags').join(' ')
|
|
||||||
|
|
||||||
defines := cmdline.many_values(args, '-d')
|
|
||||||
compile_defines, compile_defines_all := parse_defines( defines )
|
|
||||||
|
|
||||||
rdir := os.realpath(dir)
|
|
||||||
rdir_name := filepath.filename(rdir)
|
|
||||||
if '-bare' in args {
|
|
||||||
verror('use -freestanding instead of -bare')
|
|
||||||
}
|
|
||||||
obfuscate := '-obf' in args
|
|
||||||
is_repl := '-repl' in args
|
|
||||||
pref := &pref.Preferences{
|
|
||||||
is_test: is_test
|
|
||||||
is_script: is_script
|
|
||||||
is_so: '-shared' in args
|
|
||||||
is_solive: '-solive' in args
|
|
||||||
is_prod: '-prod' in args
|
|
||||||
is_verbose: '-verbose' in args || '--verbose' in args
|
|
||||||
is_debug: '-g' in args || '-cg' in args
|
|
||||||
is_vlines: '-g' in args && !('-cg' in args)
|
|
||||||
is_keep_c: '-keep_c' in args
|
|
||||||
is_pretty_c: '-pretty_c' in args
|
|
||||||
is_cache: '-cache' in args
|
|
||||||
is_stats: '-stats' in args
|
|
||||||
obfuscate: obfuscate
|
|
||||||
is_prof: '-prof' in args
|
|
||||||
is_live: '-live' in args
|
|
||||||
sanitize: '-sanitize' in args
|
|
||||||
// nofmt: '-nofmt' in args
|
|
||||||
|
|
||||||
show_c_cmd: '-show_c_cmd' in args
|
|
||||||
translated: 'translated' in args
|
|
||||||
is_run: 'run' in args
|
|
||||||
autofree: '-autofree' in args
|
|
||||||
compress: '-compress' in args
|
|
||||||
enable_globals: '--enable-globals' in args
|
|
||||||
fast: '-fast' in args
|
|
||||||
is_bare: '-freestanding' in args
|
|
||||||
x64: '-x64' in args
|
|
||||||
output_cross_c: '-output-cross-platform-c' in args
|
|
||||||
prealloc: '-prealloc' in args
|
|
||||||
is_repl: is_repl
|
|
||||||
build_mode: build_mode
|
|
||||||
cflags: cflags
|
|
||||||
ccompiler: find_c_compiler()
|
|
||||||
building_v: !is_repl && (rdir_name == 'compiler' || rdir_name == 'v.v' || rdir_name == 'vfmt.v' || dir.contains('vlib'))
|
|
||||||
// is_fmt: comptime_define == 'vfmt'
|
|
||||||
|
|
||||||
user_mod_path: user_mod_path
|
|
||||||
vlib_path: vlib_path
|
|
||||||
vpath: vpath
|
|
||||||
v2: '-v2' in args
|
|
||||||
}
|
|
||||||
if pref.is_verbose || pref.is_debug {
|
|
||||||
println('C compiler=$pref.ccompiler')
|
|
||||||
}
|
|
||||||
if pref.is_so {
|
|
||||||
out_name_c = get_vtmp_filename(out_name, '.tmp.so.c')
|
|
||||||
}
|
|
||||||
$if !linux {
|
|
||||||
if pref.is_bare && !out_name.ends_with('.c') {
|
|
||||||
verror('-freestanding only works on Linux for now')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &V{
|
|
||||||
os: _os
|
|
||||||
out_name: out_name
|
|
||||||
dir: dir
|
|
||||||
compiled_dir: if os.is_dir(rdir) { rdir } else { filepath.dir(rdir) }
|
|
||||||
lang_dir: vroot
|
|
||||||
table: new_table(obfuscate)
|
|
||||||
out_name_c: out_name_c
|
|
||||||
cgen: new_cgen(out_name_c)
|
|
||||||
//x64: x64.new_gen(out_name)
|
|
||||||
vroot: vroot
|
|
||||||
pref: pref
|
|
||||||
mod: mod
|
|
||||||
vgen_buf: vgen_buf
|
|
||||||
compile_defines: compile_defines
|
|
||||||
compile_defines_all: compile_defines_all
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn non_empty(a []string) []string {
|
|
||||||
return a.filter(it.len != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn env_vflags_and_os_args() []string {
|
|
||||||
vosargs := os.getenv('VOSARGS')
|
|
||||||
if '' != vosargs {
|
|
||||||
return non_empty(vosargs.split(' '))
|
|
||||||
}
|
|
||||||
mut args := []string
|
|
||||||
vflags := os.getenv('VFLAGS')
|
|
||||||
if '' != vflags {
|
|
||||||
args << os.args[0]
|
|
||||||
args << vflags.split(' ')
|
|
||||||
if os.args.len > 1 {
|
|
||||||
args << os.args[1..]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args << os.args
|
|
||||||
}
|
|
||||||
return non_empty(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_symlink() {
|
|
||||||
$if windows {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
vexe := vexe_path()
|
|
||||||
mut link_path := '/usr/local/bin/v'
|
|
||||||
mut ret := os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
|
||||||
if ret.exit_code == 0 {
|
|
||||||
println('Symlink "$link_path" has been created')
|
|
||||||
}
|
|
||||||
else if os.system('uname -o | grep -q \'[A/a]ndroid\'') == 0 {
|
|
||||||
println('Failed to create symlink "$link_path". Trying again with Termux path for Android.')
|
|
||||||
link_path = '/data/data/com.termux/files/usr/bin/v'
|
|
||||||
ret = os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
|
||||||
if ret.exit_code == 0 {
|
|
||||||
println('Symlink "$link_path" has been created')
|
|
||||||
} else {
|
|
||||||
println('Failed to create symlink "$link_path". Try again with sudo.')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println('Failed to create symlink "$link_path". Try again with sudo.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vexe_path() string {
|
pub fn vexe_path() string {
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
if '' != vexe {
|
if '' != vexe {
|
||||||
|
@ -1223,12 +923,3 @@ pub fn set_vroot_folder(vroot_path string) {
|
||||||
vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
|
vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
|
||||||
os.setenv('VEXE', os.realpath([vroot_path, vname].join(os.path_separator)), true)
|
os.setenv('VEXE', os.realpath([vroot_path, vname].join(os.path_separator)), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_v_compiler_with_args(args []string) &V {
|
|
||||||
vexe := vexe_path()
|
|
||||||
mut allargs := [vexe]
|
|
||||||
allargs << args
|
|
||||||
os.setenv('VOSARGS', allargs.join(' '), true)
|
|
||||||
return new_v(allargs)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
strings
|
strings
|
||||||
os
|
os
|
||||||
filepath
|
filepath
|
||||||
|
v.pref
|
||||||
)
|
)
|
||||||
/*
|
/*
|
||||||
.vh generation logic.
|
.vh generation logic.
|
||||||
|
@ -52,7 +53,11 @@ fn generate_vh(mod string) {
|
||||||
filtered := vfiles.filter(it.ends_with('.v') && !it.ends_with('test.v') && !it.ends_with('_windows.v') && !it.ends_with('_win.v') && !it.ends_with('_lin.v') && !it.contains('${os.path_separator}examples') && !it.contains('_js.v') && !it.contains('_bare.v') && !it.contains('${os.path_separator}js')) // TODO merge once filter allows it
|
filtered := vfiles.filter(it.ends_with('.v') && !it.ends_with('test.v') && !it.ends_with('_windows.v') && !it.ends_with('_win.v') && !it.ends_with('_lin.v') && !it.contains('${os.path_separator}examples') && !it.contains('_js.v') && !it.contains('_bare.v') && !it.contains('${os.path_separator}js')) // TODO merge once filter allows it
|
||||||
// println('f:')
|
// println('f:')
|
||||||
// println(filtered)
|
// println(filtered)
|
||||||
mut v := new_v(['foo.v'])
|
mut pref := &pref.Preferences {
|
||||||
|
path: 'foo.v'
|
||||||
|
}
|
||||||
|
pref.fill_with_defaults()
|
||||||
|
mut v := new_v(pref)
|
||||||
// v.pref.generating_vh = true
|
// v.pref.generating_vh = true
|
||||||
mut g := VhGen{
|
mut g := VhGen{
|
||||||
consts: strings.new_builder(1000)
|
consts: strings.new_builder(1000)
|
||||||
|
@ -166,4 +171,3 @@ fn (g mut VhGen) generate_type() {
|
||||||
// g.i = old
|
// g.i = old
|
||||||
// g.i--
|
// g.i--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,14 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module compiler
|
module compiler
|
||||||
|
|
||||||
import os
|
import (
|
||||||
import filepath
|
filepath
|
||||||
|
os
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
v_modules_path = os.home_dir() + '.vmodules'
|
v_modules_path = pref.default_module_path
|
||||||
)
|
)
|
||||||
// Holds import information scoped to the parsed file
|
// Holds import information scoped to the parsed file
|
||||||
struct ImportTable {
|
struct ImportTable {
|
||||||
|
|
|
@ -206,16 +206,16 @@ pub fn (v mut V) cc_msvc() {
|
||||||
a << '/MDd'
|
a << '/MDd'
|
||||||
}
|
}
|
||||||
if v.pref.is_so {
|
if v.pref.is_so {
|
||||||
if !v.out_name.ends_with('.dll') {
|
if !v.pref.out_name.ends_with('.dll') {
|
||||||
v.out_name = v.out_name + '.dll'
|
v.pref.out_name += '.dll'
|
||||||
}
|
}
|
||||||
// Build dll
|
// Build dll
|
||||||
a << '/LD'
|
a << '/LD'
|
||||||
}
|
}
|
||||||
else if !v.out_name.ends_with('.exe') {
|
else if !v.pref.out_name.ends_with('.exe') {
|
||||||
v.out_name = v.out_name + '.exe'
|
v.pref.out_name += '.exe'
|
||||||
}
|
}
|
||||||
v.out_name = os.realpath(v.out_name)
|
v.pref.out_name = os.realpath(v.pref.out_name)
|
||||||
// alibs := []string // builtin.o os.o http.o etc
|
// alibs := []string // builtin.o os.o http.o etc
|
||||||
if v.pref.build_mode == .build_module {
|
if v.pref.build_mode == .build_module {
|
||||||
// Compile only
|
// Compile only
|
||||||
|
@ -263,7 +263,7 @@ pub fn (v mut V) cc_msvc() {
|
||||||
a << real_libs.join(' ')
|
a << real_libs.join(' ')
|
||||||
a << '/link'
|
a << '/link'
|
||||||
a << '/NOLOGO'
|
a << '/NOLOGO'
|
||||||
a << '/OUT:"$v.out_name"'
|
a << '/OUT:"$v.pref.out_name"'
|
||||||
a << '/LIBPATH:"$r.ucrt_lib_path"'
|
a << '/LIBPATH:"$r.ucrt_lib_path"'
|
||||||
a << '/LIBPATH:"$r.um_lib_path"'
|
a << '/LIBPATH:"$r.um_lib_path"'
|
||||||
a << '/LIBPATH:"$r.vs_lib_path"'
|
a << '/LIBPATH:"$r.vs_lib_path"'
|
||||||
|
|
|
@ -6,7 +6,7 @@ module compiler
|
||||||
import os
|
import os
|
||||||
import filepath
|
import filepath
|
||||||
|
|
||||||
pub fn get_vtmp_folder() string {
|
fn get_vtmp_folder() string {
|
||||||
vtmp := filepath.join(os.tmpdir(),'v')
|
vtmp := filepath.join(os.tmpdir(),'v')
|
||||||
if !os.is_dir(vtmp) {
|
if !os.is_dir(vtmp) {
|
||||||
os.mkdir(vtmp)or{
|
os.mkdir(vtmp)or{
|
||||||
|
@ -16,7 +16,7 @@ pub fn get_vtmp_folder() string {
|
||||||
return vtmp
|
return vtmp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_vtmp_filename(base_file_name string, postfix string) string {
|
fn get_vtmp_filename(base_file_name string, postfix string) string {
|
||||||
vtmp := get_vtmp_folder()
|
vtmp := get_vtmp_folder()
|
||||||
return os.realpath(filepath.join(vtmp,filepath.filename(os.realpath(base_file_name)) + postfix))
|
return os.realpath(filepath.join(vtmp,filepath.filename(os.realpath(base_file_name)) + postfix))
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
// branch prediction hints. the C version will be
|
// branch prediction hints. the C version will be
|
||||||
// removed once the perfomance is matched.
|
// removed once the perfomance is matched.
|
||||||
// you can test performance by running:
|
// you can test performance by running:
|
||||||
// `v run tools/bench/wyhash.v`
|
// `v run cmd/tools/bench/wyhash.v`
|
||||||
// try running with and without the `-prod` flag
|
// try running with and without the `-prod` flag
|
||||||
module wyhash
|
module wyhash
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub fn (b &Builder) v_files_from_dir(dir string) []string {
|
||||||
if !os.exists(dir) {
|
if !os.exists(dir) {
|
||||||
if dir == 'compiler' && os.is_dir('vlib') {
|
if dir == 'compiler' && os.is_dir('vlib') {
|
||||||
println('looks like you are trying to build V with an old command')
|
println('looks like you are trying to build V with an old command')
|
||||||
println('use `v -o v v.v` instead of `v -o v compiler`')
|
println('use `v -o v cmd/v` instead of `v -o v compiler`')
|
||||||
}
|
}
|
||||||
verror("$dir doesn't exist")
|
verror("$dir doesn't exist")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright (c) 2019-2020 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 pref
|
||||||
|
|
||||||
|
import (
|
||||||
|
filepath
|
||||||
|
os
|
||||||
|
)
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
default_module_path = os.home_dir() + '.vmodules'
|
||||||
|
)
|
||||||
|
|
||||||
|
pub fn (p mut Preferences) fill_with_defaults() {
|
||||||
|
if p.vroot == '' {
|
||||||
|
// Location of all vlib files
|
||||||
|
p.vroot = filepath.dir(vexe_path())
|
||||||
|
}
|
||||||
|
if p.vlib_path == '' {
|
||||||
|
p.vlib_path = filepath.join(p.vroot,'vlib')
|
||||||
|
}
|
||||||
|
if p.vpath == '' {
|
||||||
|
p.vpath = default_module_path
|
||||||
|
}
|
||||||
|
if p.out_name == ''{
|
||||||
|
rpath := os.realpath(p.path)
|
||||||
|
filename := filepath.filename(rpath).trim_space()
|
||||||
|
mut base := filename.all_before_last('.')
|
||||||
|
if base == '' {
|
||||||
|
// The file name is just `.v` or `.vsh` or `.*`
|
||||||
|
base = filename
|
||||||
|
}
|
||||||
|
target_dir := if os.is_dir(rpath) { rpath } else { filepath.dir(rpath) }
|
||||||
|
p.out_name = filepath.join(target_dir, base)
|
||||||
|
|
||||||
|
if rpath == '$p.vroot/cmd/v' && os.is_dir('vlib/compiler') {
|
||||||
|
// Building V? Use v2, since we can't overwrite a running
|
||||||
|
// executable on Windows + the precompiled V is more
|
||||||
|
// optimized.
|
||||||
|
println('Saving the resulting V executable in `./v2`')
|
||||||
|
println('Use `v -o v cmd/v` if you want to replace current ' + 'V executable.')
|
||||||
|
p.out_name = 'v2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.os == ._auto {
|
||||||
|
// No OS specifed? Use current system
|
||||||
|
p.os = get_host_os()
|
||||||
|
}
|
||||||
|
if p.ccompiler == '' {
|
||||||
|
p.ccompiler = default_c_compiler()
|
||||||
|
}
|
||||||
|
p.is_test = p.path.ends_with('_test.v')
|
||||||
|
p.is_script = p.path.ends_with('.v') || p.path.ends_with('.vsh')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_c_compiler() string {
|
||||||
|
// fast_clang := '/usr/local/Cellar/llvm/8.0.0/bin/clang'
|
||||||
|
// if os.exists(fast_clang) {
|
||||||
|
// return fast_clang
|
||||||
|
// }
|
||||||
|
// TODO fix $if after 'string'
|
||||||
|
$if windows {
|
||||||
|
return 'gcc'
|
||||||
|
}
|
||||||
|
return 'cc'
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Remove code duplication
|
||||||
|
fn vexe_path() string {
|
||||||
|
vexe := os.getenv('VEXE')
|
||||||
|
if vexe != '' {
|
||||||
|
return vexe
|
||||||
|
}
|
||||||
|
real_vexe_path := os.realpath(os.executable())
|
||||||
|
os.setenv('VEXE', real_vexe_path, true)
|
||||||
|
return real_vexe_path
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
// Copyright (c) 2019-2020 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 pref
|
||||||
|
|
||||||
|
pub enum OS {
|
||||||
|
_auto // Reserved so .mac cannot be misunderstood as auto
|
||||||
|
mac
|
||||||
|
linux
|
||||||
|
windows
|
||||||
|
freebsd
|
||||||
|
openbsd
|
||||||
|
netbsd
|
||||||
|
dragonfly
|
||||||
|
js // TODO
|
||||||
|
android
|
||||||
|
solaris
|
||||||
|
haiku
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to convert string names to OS enum
|
||||||
|
pub fn os_from_string(os_str string) OS {
|
||||||
|
match os_str {
|
||||||
|
'linux' {
|
||||||
|
return .linux
|
||||||
|
}
|
||||||
|
'windows' {
|
||||||
|
return .windows
|
||||||
|
}
|
||||||
|
'mac' {
|
||||||
|
return .mac
|
||||||
|
}
|
||||||
|
'macos' {
|
||||||
|
return .mac
|
||||||
|
}
|
||||||
|
'freebsd' {
|
||||||
|
return .freebsd
|
||||||
|
}
|
||||||
|
'openbsd' {
|
||||||
|
return .openbsd
|
||||||
|
}
|
||||||
|
'netbsd' {
|
||||||
|
return .netbsd
|
||||||
|
}
|
||||||
|
'dragonfly' {
|
||||||
|
return .dragonfly
|
||||||
|
}
|
||||||
|
'js' {
|
||||||
|
return .js
|
||||||
|
}
|
||||||
|
'solaris' {
|
||||||
|
return .solaris
|
||||||
|
}
|
||||||
|
'android' {
|
||||||
|
return .android
|
||||||
|
}
|
||||||
|
'haiku' {
|
||||||
|
return .haiku
|
||||||
|
}
|
||||||
|
'linux_or_macos' {
|
||||||
|
return .linux
|
||||||
|
}
|
||||||
|
'' {
|
||||||
|
return ._auto
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panic('bad os $os_str')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (o OS) str() string {
|
||||||
|
match o {
|
||||||
|
._auto {
|
||||||
|
return 'RESERVED: AUTO'
|
||||||
|
}
|
||||||
|
.mac {
|
||||||
|
return 'MacOS'
|
||||||
|
}
|
||||||
|
.linux {
|
||||||
|
return 'Linux'
|
||||||
|
}
|
||||||
|
.windows {
|
||||||
|
return 'Windows'
|
||||||
|
}
|
||||||
|
.freebsd {
|
||||||
|
return 'FreeBSD'
|
||||||
|
}
|
||||||
|
.openbsd {
|
||||||
|
return 'OpenBSD'
|
||||||
|
}
|
||||||
|
.netbsd {
|
||||||
|
return 'NetBSD'
|
||||||
|
}
|
||||||
|
.dragonfly {
|
||||||
|
return 'Dragonfly'
|
||||||
|
}
|
||||||
|
.js {
|
||||||
|
return 'JavaScript'
|
||||||
|
}
|
||||||
|
.android {
|
||||||
|
return 'Android'
|
||||||
|
}
|
||||||
|
.solaris {
|
||||||
|
return 'Solaris'
|
||||||
|
}
|
||||||
|
.haiku {
|
||||||
|
return 'Haiku'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//TODO Remove when V is smart enough to know that there's no other possibilities
|
||||||
|
//should never be reached as all enum types have been enumerated
|
||||||
|
panic('unknown OS enum type: $o')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_host_os() OS {
|
||||||
|
$if linux {
|
||||||
|
return .linux
|
||||||
|
}
|
||||||
|
$if macos {
|
||||||
|
return .mac
|
||||||
|
}
|
||||||
|
$if windows {
|
||||||
|
return .windows
|
||||||
|
}
|
||||||
|
$if freebsd {
|
||||||
|
return .freebsd
|
||||||
|
}
|
||||||
|
$if openbsd {
|
||||||
|
return .openbsd
|
||||||
|
}
|
||||||
|
$if netbsd {
|
||||||
|
return .netbsd
|
||||||
|
}
|
||||||
|
$if dragonfly {
|
||||||
|
return .dragonfly
|
||||||
|
}
|
||||||
|
$if solaris {
|
||||||
|
return .solaris
|
||||||
|
}
|
||||||
|
$if haiku {
|
||||||
|
return .haiku
|
||||||
|
}
|
||||||
|
panic('unknown host OS')
|
||||||
|
}
|
|
@ -12,22 +12,9 @@ pub enum BuildMode {
|
||||||
build_module
|
build_module
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum OS {
|
|
||||||
mac
|
|
||||||
linux
|
|
||||||
windows
|
|
||||||
freebsd
|
|
||||||
openbsd
|
|
||||||
netbsd
|
|
||||||
dragonfly
|
|
||||||
js // TODO
|
|
||||||
android
|
|
||||||
solaris
|
|
||||||
haiku
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Preferences {
|
pub struct Preferences {
|
||||||
pub mut:
|
pub mut:
|
||||||
|
os OS // the OS to compile for
|
||||||
build_mode BuildMode
|
build_mode BuildMode
|
||||||
// nofmt bool // disable vfmt
|
// nofmt bool // disable vfmt
|
||||||
is_test bool // `v test string_test.v`
|
is_test bool // `v test string_test.v`
|
||||||
|
@ -58,6 +45,7 @@ pub mut:
|
||||||
// You could pass several -cflags XXX arguments. They will be merged with each other.
|
// You could pass several -cflags XXX arguments. They will be merged with each other.
|
||||||
// You can also quote several options at the same time: -cflags '-Os -fno-inline-small-functions'.
|
// You can also quote several options at the same time: -cflags '-Os -fno-inline-small-functions'.
|
||||||
ccompiler string // the name of the used C compiler
|
ccompiler string // the name of the used C compiler
|
||||||
|
third_party_option string
|
||||||
building_v bool
|
building_v bool
|
||||||
autofree bool
|
autofree bool
|
||||||
compress bool
|
compress bool
|
||||||
|
@ -77,4 +65,13 @@ pub mut:
|
||||||
output_cross_c bool
|
output_cross_c bool
|
||||||
prealloc bool
|
prealloc bool
|
||||||
v2 bool
|
v2 bool
|
||||||
|
vroot string
|
||||||
|
out_name string
|
||||||
|
path string // Path to file/folder to compile
|
||||||
|
|
||||||
|
// -d vfmt and -d another=0 for `$if vfmt { will execute }` and `$if another { will NOT get here }`
|
||||||
|
compile_defines []string // just ['vfmt']
|
||||||
|
compile_defines_all []string // contains both: ['vfmt','another']
|
||||||
|
|
||||||
|
mod string
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue