diff --git a/.github/Ubuntu/build.sh b/.github/Ubuntu/build.sh new file mode 100755 index 00000000..1ff4d90f --- /dev/null +++ b/.github/Ubuntu/build.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -e + +function Usage { + echo "Usage: build.sh [-f]" +} + +if [ $# -gt 1 ]; then + Usage + exit 1 +fi + +if [ $# -eq 1 ] && [ "$1" != "-f" ]; then + Usage + exit 1 +fi + +export VCPROOT="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +export PATH="${VCPROOT}/vl/cmd:${PATH}" +export SHELL=/bin/bash + +vmake --make + +if [ "$1" == "-f" ]; then + vbuild -f +else + vbuild -b +fi diff --git a/.github/Ubuntu/vl/cmd/vbuild b/.github/Ubuntu/vl/cmd/vbuild new file mode 100755 index 00000000..eb0e191c --- /dev/null +++ b/.github/Ubuntu/vl/cmd/vbuild @@ -0,0 +1,158 @@ +#!/bin/bash + +function Help { + echo "Usage:" + echo "--clean" + echo " Clean generated files." + echo "-b, --build" + echo " Incrementally build the current folder." + echo "-f, --full-build, -f" + echo " Rebuild the current folder." + echo "-c, --build-coverage" + echo " Rebuild the current folder with coverage." + echo "-fc, --full-build-coverage" + echo " Rebuild the current folder with coverage." + echo "--build-gcc" + echo " Incrementally build the current folder using G++." + echo "--full-build-gcc" + echo " Rebuild the current folder using G++." + echo "-g, --generate" + echo " Generate coverage data." + echo "-r, --read" + echo " Read coverage data." +} + +function Check { + if ! [ -a vmake ]; then + echo "Cannot find ./vmake ." + exit 1 + fi +} + +function Clean { + Check + make clean +} + +function Build { + Check + make +} + +function FullBuild { + Check + make clean + make +} + +function BuildCoverage { + Check + make COVERAGE=YES +} + +function FullBuildCoverage { + Check + make clean + make COVERAGE=YES +} + +function BuildGCC { + Check + make USE_GCC=YES +} + +function FullBuildGCC { + Check + make clean + make USE_GCC=YES +} + +function Generate { + Check + lcov --directory ./Obj/ --base-directory . --gcov-tool ${VCPROOT}/vl/llvm-gcov.sh --capture -o ./Coverage/cov.info + genhtml ./Coverage/cov.info -o ./Coverage/HTML/ +} + +function Read { + Check + firefox `pwd`/Coverage/HTML/index.html + #sensible-browser ./Coverage/HTML/index.html +} + +case $1 in + --help) + Help + ;; + + --clean) + Clean + ;; + + -b|--build) + Build + ;; + + -f|--full-build) + FullBuild + ;; + + -c|--build-coverage) + BuildCoverage + ;; + + -fc|--full-build-coverage) + FullBuildCoverage + ;; + + --build-gcc) + BuildGCC + ;; + + --full-build-gcc) + FullBuildGCC + ;; + + -g|--generate) + Generate + ;; + + -r|--read) + Read + ;; + + *) + echo "Use --help for more information." + ;; +esac + +# original makefile-cpp with gcc code coverage + +#COVERAGE?=NO +# +#ifeq ($(COVERAGE),NO) +#CPP_LINK=clang++ -std=c++20 -pthread -g $(CPP_COMPILE_OPTIONS) -o $@ $^ +#else +#CPP_LINK=g++ -std=c++20 -g -fprofile-arcs -pthread $(CPP_LINK_OPTIONS) -o $@ $^ +#endif +# +#ifeq ($(COVERAGE),NO) +#CPP_COMPILE=clang++ -std=c++20 -g $(CPP_COMPILE_OPTIONS) -o $@ -c $< +#else +#CPP_COMPILE=g++ -std=c++20 -g -fprofile-arcs -ftest-coverage $(CPP_COMPILE_OPTIONS) -o $@ -c $< +#endif + +#function Generate { +# Check +# PATTERN='^(.+)?\.o:\s*((.+)?.cpp).*$' +# CPP_FILES=`cat makefile \ +# | grep -E ${PATTERN} \ +# | sed -r -e 's%'${PATTERN}'%../\2%g' +# ` +# rm -rf ./Coverage/* +# gcov -o ./Obj/ ${CPP_FILES} > /dev/null +# mv -f *.gcov ./Coverage/ +# pushd ./Coverage > /dev/null +# lcov --directory ../Obj/ --capture --output-file lcov.info +# genhtml -o HTML lcov.info > /dev/null +# popd > /dev/null +#} \ No newline at end of file diff --git a/.github/Ubuntu/vl/cmd/vmake b/.github/Ubuntu/vl/cmd/vmake new file mode 100755 index 00000000..12ba752e --- /dev/null +++ b/.github/Ubuntu/vl/cmd/vmake @@ -0,0 +1,30 @@ +#!/bin/bash + +function Help { + echo "Usage:" + echo "--make" + echo " Update ./makefile and ./vmake.txt from ./vmake." +} + +function Make { + if [ -a vmake ]; then + vt4 --preprocess ./vmake | vt4 --evaluate | ${SHELL} > makefile + else + echo "Cannot find ./vmake ." + exit 1 + fi +} + +case $1 in + --help) + Help + ;; + + --make) + Make + ;; + + *) + echo "Use --help for more information." + ;; +esac diff --git a/.github/Ubuntu/vl/cmd/vt4 b/.github/Ubuntu/vl/cmd/vt4 new file mode 100755 index 00000000..34e35db1 --- /dev/null +++ b/.github/Ubuntu/vl/cmd/vt4 @@ -0,0 +1,123 @@ +#!/bin/bash + +function Help { + echo "Usage:" + echo "--preprocess " + echo " Preprocess the template file and print to standard output." + echo "--evaluate " + echo " Evaluate the preprocessed template file and print to standard output." +} + +function Error { + (>&2 echo "Error(Row:${ROW_NUMBER}, Col:${COLUMN_NUMBER}): $1") + (>&2 echo " In: ${LINE}") + exit 1 +} + +function Preprocess { + PATTERN='^\s*<#@\s*include\s*"([^"]*)"\s*#>\s*$' + cat $1 | while read -r LINE; do + INCLUDE_STAT=`echo "${LINE}" | grep -E ${PATTERN}` + if [[ "$INCLUDE_STAT" == "" ]]; then + echo "${LINE}" + else + INCLUDE_FILE=`echo "${LINE}" | sed -r -e 's%'${PATTERN}'%\1%g'` + INCLUDE_DIR=`dirname ${INCLUDE_FILE}` + INCLUDE_NAME=`basename ${INCLUDE_FILE}` + + eval INCLUDE_DIR=$INCLUDE_DIR + pushd ${INCLUDE_DIR} > /dev/null + vt4 --preprocess "${INCLUDE_NAME}" + popd > /dev/null + fi + done +} + +function Evaluate { + STATE_TEXT=1 + STATE_CODE=2 + STATE_EXPR=3 + + STATE=$STATE_TEXT + ROW_NUMBER=1 + + echo "#!/bin/bash" + echo "" + + cat $1 | while read -r LINE; do + COLUMN_NUMBER=0 + + PARTS=`echo $LINE | sed -r -e 's%(<#=\s*|<#\s*|\s*#>)%\n\1\n%g'` + PARTS=`echo "$PARTS" | sed -r -e 's%^<#=\s*$%<#=%g;s%^<#\s*$%<#%g;s%^\s*#>$%#>%g'` + PURE_COMMAND=1 + + while read -r PART; do + case "$PART" in + "") + ;; + + "<#") + if [ $STATE == $STATE_TEXT ]; then + STATE=$STATE_CODE + else + Error "\"<#\" and \"<#=\" cannot be embedded in each other." + fi + ;; + + "<#=") + if [ $STATE == $STATE_TEXT ]; then + STATE=$STATE_EXPR + else + Error "\"<#\" and \"<#=\" cannot be embedded in each other." + fi + ;; + + "#>") + if [ $STATE == $STATE_TEXT ]; then + Error "Wrong place for \"#>\"." + else + STATE=$STATE_TEXT + fi + ;; + + *) + if [ $STATE == $STATE_CODE ]; then + echo "${PART}" + elif [ $STATE == $STATE_EXPR ]; then + PURE_COMMAND=0 + echo "echo -n ${PART}" + else + PURE_COMMAND=0 + echo "echo -n '${PART}'" + fi + ;; + esac + + COLUMN_NUMBER=`echo "$(($COLUMN_NUMBER+${#PARTS}))"` + done <<< "${PARTS}" + + if ( [ "$LINE" == "" ] && [ $STATE == $STATE_TEXT ] ) || [ $PURE_COMMAND == 0 ]; then + echo 'echo ""' + fi + ROW_NUMBER=`echo "$(($ROW_NUMBER+1))"` + done +} + +IFS= +case $1 in + --help) + Help + ;; + + --preprocess) + Preprocess $2 + ;; + + --evaluate) + Evaluate $2 + ;; + + *) + echo "Use --help for more information." + ;; +esac diff --git a/.github/Ubuntu/vl/cmd/vutil_CppDependencies b/.github/Ubuntu/vl/cmd/vutil_CppDependencies new file mode 100755 index 00000000..b16f3dfb --- /dev/null +++ b/.github/Ubuntu/vl/cmd/vutil_CppDependencies @@ -0,0 +1,3 @@ +#!/bin/bash + +echo `clang++ --std=c++20 $1 -MM $2` | sed -r -e 's%[\]\s*%%g' diff --git a/.github/Ubuntu/vl/cmd/vutil_CppFromVcxproj b/.github/Ubuntu/vl/cmd/vutil_CppFromVcxproj new file mode 100755 index 00000000..45689d82 --- /dev/null +++ b/.github/Ubuntu/vl/cmd/vutil_CppFromVcxproj @@ -0,0 +1,19 @@ +#!/bin/bash + +# read the input *.vcxproj +if [ "$1" == "" ]; then + exit 0 +fi +CONTENT=`cat $1` + +# extract all cpp files +PATTERN='' +COMPILES=`echo "${CONTENT}" | grep -E ${PATTERN}` +CPPS=`echo "${COMPILES}" | sed -r -e 's%\s*'${PATTERN}'\s*%\2%g'` + +# refine file names +CPPS=`echo "${CPPS}" | sed -e 's%[\]%/%g'` +CPPS=`echo "${CPPS}" | sed -e 's%^%'${PWD}/$(dirname $1)/'%g'` +echo "${CPPS}" | while read -r CPP; do + realpath --relative-to="${PWD}" ${CPP} +done diff --git a/.github/Ubuntu/vl/makefile-cpp b/.github/Ubuntu/vl/makefile-cpp new file mode 100644 index 00000000..7256e5d2 --- /dev/null +++ b/.github/Ubuntu/vl/makefile-cpp @@ -0,0 +1,20 @@ +COVERAGE?=NO +USE_GCC?=NO + +# add "--stdlib=libc++" after bug #808086 is fixed + +ifeq ($(USE_GCC), YES) +CPP_LINK=g++ -std=c++20 -g -pthread $(CPP_LINK_OPTIONS) -o $@ $^ +else ifeq ($(COVERAGE),NO) +CPP_LINK=clang++ -std=c++20 -pthread -g $(CPP_COMPILE_OPTIONS) -o $@ $^ +else +CPP_LINK=clang++ -std=c++20 -pthread -g --coverage $(CPP_LINK_OPTIONS) -o $@ $^ +endif + +ifeq ($(USE_GCC), YES) +CPP_COMPILE=g++ -std=c++20 -g $(CPP_COMPILE_OPTIONS) -o $@ -c $< +else ifeq ($(COVERAGE),NO) +CPP_COMPILE=clang++ -std=c++20 -g $(CPP_COMPILE_OPTIONS) -o $@ -c $< +else +CPP_COMPILE=clang++ -std=c++20 -g -fprofile-arcs -ftest-coverage $(CPP_COMPILE_OPTIONS) -o $@ -c $< +endif diff --git a/.github/Ubuntu/vl/vmake-cpp b/.github/Ubuntu/vl/vmake-cpp new file mode 100644 index 00000000..d8a52683 --- /dev/null +++ b/.github/Ubuntu/vl/vmake-cpp @@ -0,0 +1,75 @@ +<# +if ! [ "$CPP_VCXPROJ" == "" ]; then + CPP_FILES=($(vutil_CppFromVcxproj $CPP_VCXPROJ)) +fi + +for CPP_VCXPROJ_ITEM in "${CPP_VCXPROJS[@]}"; do + CPP_FILES_FROM_VCXPROJ=($(vutil_CppFromVcxproj $CPP_VCXPROJ_ITEM)) + CPP_FILES=(${CPP_FILES[@]} ${CPP_FILES_FROM_VCXPROJ[@]}) +done + +# Remove duplicated items (preserve the first occurrence, like LINQ Distinct) +declare -A __vutil_seen_cpp_files +__vutil_distinct_cpp_files=() +for __vutil_cpp_file in "${CPP_FILES[@]}"; do + if [ "${__vutil_seen_cpp_files["${__vutil_cpp_file}"]+x}" == "" ]; then + __vutil_seen_cpp_files["${__vutil_cpp_file}"]=1 + __vutil_distinct_cpp_files+=("${__vutil_cpp_file}") + fi +done +CPP_FILES=("${__vutil_distinct_cpp_files[@]}") +unset __vutil_seen_cpp_files __vutil_distinct_cpp_files __vutil_cpp_file + +for CPP_REMOVE in "${CPP_REMOVES[@]}"; do + CPP_FILES=(${CPP_FILES[@]/$CPP_REMOVE}) +done + +for CPP_ADD in "${CPP_ADDS[@]}"; do + CPP_FILES=(${CPP_FILES[@]} $CPP_ADD) +done + +CPP_FILE_LIST=("${CPP_FILES[@]}") +printf -v CPP_FILES "%s\n" "${CPP_FILE_LIST[@]}" +CPP_FILES=${CPP_FILES%?} + +O_FILES=`echo "${CPP_FILES}" | sed -r -e 's%([^/]*/)*([^/]+).cpp%./Obj/\2.o%g'` +O_FILES=`echo ${O_FILES}` + +printf "%s\n" "${CPP_FILE_LIST[@]}" > vmake.txt +#> +.PHONY: all clean pre-build +.DEFAULT_GOAL := all + +<#if ! [ "$CPP_COMPILE_OPTIONS" == "" ]; then#> +CPP_COMPILE_OPTIONS=<#= $CPP_COMPILE_OPTIONS #> +<#fi#> +<#if ! [ "$CPP_LINK_OPTIONS" == "" ]; then#> +CPP_LINK_OPTIONS = <#= $CPP_LINK_OPTIONS #> +<#fi#> +include $(VCPROOT)/vl/makefile-cpp + +pre-build: + if ! [ -d ./Bin ]; then mkdir ./Bin; fi + if ! [ -d ./Obj ]; then mkdir ./Obj; fi + if ! [ -d ./Coverage ]; then mkdir ./Coverage; fi +<#for FOLDER in "${FOLDERS[@]}"; do#> + if ! [ -d <#= $FOLDER #> ]; then mkdir <#= $FOLDER #>; fi +<#done#> + +clean: + if [ -d ./Bin ]; then rm -r ./Bin; fi + if [ -d ./Obj ]; then rm -r ./Obj; fi + if [ -d ./Coverage ]; then rm -r ./Coverage; fi +<#for FOLDER in "${FOLDERS[@]}"; do#> + if [ -d ./<#= $FOLDER #> ]; then rm -r <#= $FOLDER #>; fi +<#done#> + +all:pre-build <#= ${TARGETS[@]} #> + +<#= $CPP_TARGET #>:<#= ${O_FILES} #> + $(CPP_LINK) +<#echo "${CPP_FILES}" | while read -r CPP_FILE; do#> + +./Obj/<#= `vutil_CppDependencies "${CPP_COMPILE_OPTIONS}" ${CPP_FILE}` #> + $(CPP_COMPILE) +<#done#>