From adeebad2a6b383c7e9d45407814a838142ff149d Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 29 Nov 2020 17:18:49 +0200 Subject: [PATCH] compiler: use thirdparty/tcc/tcc.exe by default, when no explicit -cc is given (#6598) --- .github/workflows/ci.yml | 21 +++++------ Makefile | 29 +++++++------- cmd/tools/vdoctor.v | 3 -- make.bat | 12 ++++-- vlib/v/builder/cc.v | 81 +++++++++++++++++----------------------- vlib/v/gen/cheaders.v | 5 +++ vlib/v/pref/default.v | 30 ++++++++++++++- vlib/v/pref/pref.v | 4 +- 8 files changed, 105 insertions(+), 80 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62a374f37a..b4f360c08f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: runs-on: ubuntu-18.04 timeout-minutes: 30 env: - VFLAGS: -cc /var/tmp/tcc/bin/tcc -cflags -bt10 + VFLAGS: -cc tcc -cflags -bt10 steps: - uses: actions/checkout@v2 - name: Install dependencies @@ -83,12 +83,12 @@ jobs: - name: Build v run: | echo $VFLAGS + sudo ln -s $PWD/thirdparty/tcc/tcc.exe /usr/local/bin/tcc ## TODO: remove make -j4 ./v -cg -o v cmd/v - name: Test v->c run: | - sudo ln -s /var/tmp/tcc/bin/tcc /usr/local/bin/tcc - tcc -version + thirdparty/tcc/tcc.exe -version ./v -cg -o v cmd/v # Make sure vtcc can build itself twice # ./v -silent test-compiler - name: v self compilation @@ -112,7 +112,7 @@ jobs: image: thevlang/vlang:alpine-build env: V_CI_MUSL: 1 - + VFLAGS: -cc gcc volumes: - ${{github.workspace}}:/opt/vlang steps: @@ -127,11 +127,10 @@ jobs: v -silent test-fixed macos: - runs-on: ${{ matrix.os }} + runs-on: macOS-latest timeout-minutes: 30 - strategy: - matrix: - os: [macOS-latest] + env: + VFLAGS: -cc clang steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 @@ -146,11 +145,11 @@ jobs: ## brew install sdl2 sdl2_ttf sdl2_mixer sdl2_image export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/opt/openssl/lib/" - name: Build V - run: make -j4 && ./v -cg -o v cmd/v + run: make -j4 && ./v -o v cmd/v - name: Build V using V run: ./v -o v2 cmd/v && ./v2 -o v3 cmd/v - name: Test symlink - run: sudo ./v symlink + run: ./v symlink # - name: Set up pg database # run: | # pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start @@ -163,8 +162,6 @@ jobs: # run: ./v -silent build-vbinaries ## - name: Test v->js ## run: ./v -o hi.js examples/hello_v_js.v && node hi.js - - name: Test symlink - run: ./v symlink && v -o v2 cmd/v - name: Fixed tests run: VJOBS=1 ./v -silent test-fixed - name: Build examples diff --git a/Makefile b/Makefile index 855f91559b..bdca9cdf25 100644 --- a/Makefile +++ b/Makefile @@ -2,15 +2,17 @@ CC ?= cc CFLAGS ?= LDFLAGS ?= TMPDIR ?= /tmp +VROOT ?= . VC ?= ./vc -V := ./v +V ?= ./v +VCREPO ?= https://github.com/vlang/vc +TCCREPO ?= https://github.com/vlang/tccbin VCFILE := v.c -TMPTCC := /var/tmp/tcc -VCREPO := https://github.com/vlang/vc -TCCREPO := https://github.com/vlang/tccbin +TMPTCC := $(VROOT)/thirdparty/tcc +TCCBRANCH := thirdparty-unknown-unknown GITCLEANPULL := git clean -xf && git pull --quiet -GITFASTCLONE := git clone --depth 1 --quiet +GITFASTCLONE := git clone --depth 1 --quiet --single-branch #### Platform detections and overrides: _SYS := $(shell uname 2>/dev/null || echo Unknown) @@ -24,10 +26,12 @@ endif ifeq ($(_SYS),Linux) LINUX := 1 +TCCBRANCH := thirdparty-linux-amd64 endif ifeq ($(_SYS),Darwin) MAC := 1 +TCCBRANCH := thirdparty-macos-amd64 endif ifeq ($(_SYS),FreeBSD) @@ -37,11 +41,12 @@ endif ifdef ANDROID_ROOT ANDROID := 1 undefine LINUX +TCCBRANCH := thirdparty-linux-arm64 endif ##### ifdef WIN32 -TCCREPO := https://github.com/vlang/tccbin_win +TCCBRANCH := thirdparty-windows-amd64 VCFILE := v_win.c endif @@ -91,27 +96,25 @@ fresh_vc: latest_tcc: $(TMPTCC)/.git/config ifndef ANDROID -ifndef MAC ifndef local cd $(TMPTCC) && $(GITCLEANPULL) else @echo "Using local tcc" endif endif -endif fresh_tcc: ifndef ANDROID -ifndef MAC +ifdef LINUX + rm -rf /var/tmp/tcc + git clone https://github.com/vlang/tccbin /var/tmp/tcc +endif rm -rf $(TMPTCC) - $(GITFASTCLONE) $(TCCREPO) $(TMPTCC) -endif + $(GITFASTCLONE) --branch $(TCCBRANCH) $(TCCREPO) $(TMPTCC) endif $(TMPTCC)/.git/config: -ifndef MAC $(MAKE) fresh_tcc -endif $(VC)/.git/config: $(MAKE) fresh_vc diff --git a/cmd/tools/vdoctor.v b/cmd/tools/vdoctor.v index bacf5196fa..1db57b393a 100644 --- a/cmd/tools/vdoctor.v +++ b/cmd/tools/vdoctor.v @@ -122,9 +122,6 @@ fn (mut a App) collect_info() { a.line('Git vroot status', a.git_info()) a.line('.git/config present', os.is_file('.git/config').str()) // - if os_kind == 'linux' { - a.report_tcc_version('/var/tmp/tcc') - } a.report_tcc_version('thirdparty/tcc') } diff --git a/make.bat b/make.bat index af74f3eeb3..34181114c3 100644 --- a/make.bat +++ b/make.bat @@ -14,13 +14,17 @@ set subcmd= set target=build REM TCC variables -set "tcc_url=https://github.com/vlang/tccbin_win.git" +set "tcc_url=https://github.com/vlang/tccbin" set "tcc_dir=%~dp0thirdparty\tcc" -set "vc_url=https://github.com/vlang/vc.git" +set "tcc_branch=thirdparty-windows-amd64" + +REM VC settings +set "vc_url=https://github.com/vlang/vc" set "vc_dir=%~dp0vc" REM Let a particular environment specify their own TCC repo if /I not ["%TCC_GIT%"] == [""] set "tcc_url=%TCC_GIT%" +if /I not ["%TCC_BRANCH%"] == [""] set "tcc_branch=%TCC_BRANCH%" pushd %~dp0 @@ -227,7 +231,7 @@ if %ERRORLEVEL% NEQ 0 ( if not exist %tcc_dir% ( echo ^> TCC not found echo ^> Downloading TCC from %tcc_url% - call :buildcmd "git clone --depth 1 --quiet "!tcc_url!" "%tcc_dir%"" " " + call :buildcmd "git clone --depth 1 --quiet --single-branch --branch "!tcc_branch!" "!tcc_url!" "%tcc_dir%"" " " ) pushd %tcc_dir% || ( echo ^> TCC not found, even after cloning @@ -360,4 +364,4 @@ exit /b 0 :eof popd endlocal -exit /b 0 \ No newline at end of file +exit /b 0 diff --git a/vlib/v/builder/cc.v b/vlib/v/builder/cc.v index 11d51e3bff..4e7e17eac9 100644 --- a/vlib/v/builder/cc.v +++ b/vlib/v/builder/cc.v @@ -217,6 +217,12 @@ fn (mut v Builder) cc() { return } } + // + mut tried_compilation_commands := []string{} + original_pwd := os.getwd() + // TODO remove the start: goto start construct; + // use a labeled for break instead + start: mut ccompiler := v.pref.ccompiler $if windows { if ccompiler == 'msvc' { @@ -248,35 +254,6 @@ fn (mut v Builder) cc() { args << '-fobjc-arc' } mut linker_flags := []string{} - // TCC on Linux by default, unless -cc was provided - // TODO if -cc = cc, TCC is still used, default compiler should be - // used instead. - if v.pref.fast { - $if linux { - $if !android { - tcc_3rd := '$vdir/thirdparty/tcc/bin/tcc' - // println('tcc third "$tcc_3rd"') - tcc_path := '/var/tmp/tcc/bin/tcc' - if os.exists(tcc_3rd) && !os.exists(tcc_path) { - // println('moving tcc') - // if there's tcc in thirdparty/, that means this is - // a prebuilt V_linux.zip. - // Until the libtcc1.a bug is fixed, we neeed to move - // it to /var/tmp/ - os.system('mv $vdir/thirdparty/tcc /var/tmp/') - } - if v.pref.ccompiler == 'cc' && os.exists(tcc_path) { - // TODO tcc bug, needs an empty libtcc1.a fila - // os.mkdir('/var/tmp/tcc/lib/tcc/') or { panic(err) } - // os.create('/var/tmp/tcc/lib/tcc/libtcc1.a') - v.pref.ccompiler = tcc_path - args << '-m64' - } - } - } $else { - verror('-fast is only supported on Linux right now') - } - } if !v.pref.is_shared && v.pref.build_mode != .build_module && os.user_os() == 'windows' && !v.pref.out_name.ends_with('.exe') { v.pref.out_name += '.exe' @@ -353,9 +330,9 @@ fn (mut v Builder) cc() { } if debug_mode { args << debug_options - $if macos { - args << ' -ferror-limit=5000 ' - } + // $if macos { + // args << ' -ferror-limit=5000 ' + // } } if v.pref.is_prod { args << optimization_options @@ -448,7 +425,9 @@ fn (mut v Builder) cc() { } // macOS code can include objective C TODO remove once objective C is replaced with C if v.pref.os == .macos || v.pref.os == .ios { - args << '-x objective-c' + if !is_cc_tcc { + args << '-x objective-c' + } } // The C file we are compiling args << '"$v.out_name_c"' @@ -535,10 +514,11 @@ fn (mut v Builder) cc() { v.pref.cleanup_files << v.out_name_c v.pref.cleanup_files << response_file } - start: + // todo() - // TODO remove + os.chdir(vdir) cmd := '$ccompiler @$response_file' + tried_compilation_commands << cmd v.show_cc(cmd, response_file, response_file_content) // Run ticks := time.ticks() @@ -546,6 +526,7 @@ fn (mut v Builder) cc() { // C compilation failed. // If we are on Windows, try msvc println('C compilation failed.') + os.chdir(original_pwd) /* if os.user_os() == 'windows' && v.pref.ccompiler != 'msvc' { println('Trying to build with MSVC') @@ -561,19 +542,27 @@ fn (mut v Builder) cc() { if v.pref.show_c_output { v.show_c_compiler_output(res) } - if res.exit_code == 127 { - // the command could not be found by the system - $if linux { - // TCC problems on linux? Try GCC. - if ccompiler.contains('tcc') { - v.pref.ccompiler = 'cc' - goto start + os.chdir(original_pwd) + if res.exit_code != 0 { + if ccompiler.contains('tcc.exe') { + // a TCC problem? Retry with the system cc: + if tried_compilation_commands.len > 1 { + eprintln('Recompilation loop detected (ccompiler: $ccompiler):') + for recompile_command in tried_compilation_commands { + eprintln(' $recompile_command') + } + exit(101) } + eprintln('recompilation with tcc failed; retrying with cc ...') + v.pref.ccompiler = pref.default_c_compiler() + goto start + } + if res.exit_code == 127 { + verror('C compiler error, while attempting to run: \n' + + '-----------------------------------------------------------\n' + '$cmd\n' + + '-----------------------------------------------------------\n' + 'Probably your C compiler is missing. \n' + + 'Please reinstall it, or make it available in your PATH.\n\n' + missing_compiler_info()) } - verror('C compiler error, while attempting to run: \n' + - '-----------------------------------------------------------\n' + '$cmd\n' + - '-----------------------------------------------------------\n' + 'Probably your C compiler is missing. \n' + - 'Please reinstall it, or make it available in your PATH.\n\n' + missing_compiler_info()) } if !v.pref.show_c_output { v.post_process_c_compiler_output(res) diff --git a/vlib/v/gen/cheaders.v b/vlib/v/gen/cheaders.v index 1fc60628ca..b3d73b2cea 100644 --- a/vlib/v/gen/cheaders.v +++ b/vlib/v/gen/cheaders.v @@ -124,6 +124,11 @@ typedef int (*qsort_callback_func)(const void*, const void*); #define _MOV #endif +#if defined(__TINYC__) && defined(__has_include) +// tcc does not support has_include properly yet, turn it off completely +#undef __has_include +#endif + #ifndef _WIN32 #if defined __has_include #if __has_include () diff --git a/vlib/v/pref/default.v b/vlib/v/pref/default.v index 51765f3fd7..5fcccf7314 100644 --- a/vlib/v/pref/default.v +++ b/vlib/v/pref/default.v @@ -53,6 +53,8 @@ pub fn (mut p Preferences) fill_with_defaults() { // No OS specifed? Use current system p.os = get_host_os() } + // + p.try_to_use_tcc_by_default() if p.ccompiler == '' { p.ccompiler = default_c_compiler() } @@ -83,7 +85,33 @@ pub fn (mut p Preferences) fill_with_defaults() { // eprintln('prefs.cache_manager: $p') } -fn default_c_compiler() string { +fn (mut p Preferences) try_to_use_tcc_by_default() { + if p.ccompiler == 'tcc' { + p.ccompiler = default_tcc_compiler() + return + } + if p.ccompiler == '' { + // tcc is known to fail several tests on macos, so do not + // try to use it by default, only when it is explicitly set + $if macos { + return + } + p.ccompiler = default_tcc_compiler() + return + } +} + +pub fn default_tcc_compiler() string { + vexe := vexe_path() + vroot := os.dir(vexe) + vtccexe := os.join_path(vroot, 'thirdparty', 'tcc', 'tcc.exe') + if os.exists(vtccexe) { + return vtccexe + } + return '' +} + +pub fn default_c_compiler() string { // fast_clang := '/usr/local/Cellar/llvm/8.0.0/bin/clang' // if os.exists(fast_clang) { // return fast_clang diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index 6f128de65a..a5a245a270 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -97,7 +97,6 @@ pub mut: // This is on by default, since a vast majority of users do not // work on the builtin module itself. // generating_vh bool - fast bool // use tcc/x64 codegen enable_globals bool // allow __global for low level code is_fmt bool is_vet bool @@ -328,6 +327,9 @@ pub fn parse_args(args []string) (&Preferences, string) { if res.out_name.ends_with('.js') { res.backend = .js } + if !os.is_abs_path(res.out_name) { + res.out_name = os.join_path(os.getwd(), res.out_name) + } i++ } '-b' {