summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2022-12-14 22:19:20 +0800
committerGitHub <[email protected]>2022-12-14 22:19:20 +0800
commit47add8685e01b60412d63994cbed65f7049ae91a (patch)
treecbf213ac8b13271b809542d65cd05d6a491b7605
parent4e1325a6699ea3a0aa6cd7568e93c7a3b3ea402a (diff)
parent52c919d54bedc52b7b0af560bdb55d36d1668906 (diff)
Merge pull request #3172 from xmake-io/xmake.sh
add xmake.sh
-rwxr-xr-xconfigure3836
-rw-r--r--core/src/demo/xmake.lua2
-rwxr-xr-xcore/src/demo/xmake.sh25
-rw-r--r--core/src/lua-cjson/xmake.lua2
-rwxr-xr-xcore/src/lua-cjson/xmake.sh13
-rw-r--r--core/src/lua/xmake.lua3
-rwxr-xr-xcore/src/lua/xmake.sh53
-rw-r--r--core/src/luajit/xmake.lua5
-rwxr-xr-xcore/src/luajit/xmake.sh67
-rwxr-xr-xcore/src/lz4/xmake.sh13
-rwxr-xr-xcore/src/sv/xmake.sh8
m---------core/src/tbox/tbox0
-rwxr-xr-xcore/src/tbox/xmake.sh15
-rw-r--r--core/src/xmake/os/cpuinfo.c1
-rw-r--r--core/src/xmake/xmake.lua5
-rwxr-xr-xcore/src/xmake/xmake.sh56
-rw-r--r--core/xmake.lua4
-rwxr-xr-xcore/xmake.sh60
18 files changed, 4153 insertions, 15 deletions
diff --git a/configure b/configure
new file mode 100755
index 000000000..1ef58fc77
--- /dev/null
+++ b/configure
@@ -0,0 +1,3836 @@
+#!/bin/sh
+# A script-only build utility like autotools
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http:##www.apache.org#licenses#LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Copyright (C) 2022-present, TBOOX Open Source Group.
+#
+# @author ruki
+#
+
+#-----------------------------------------------------------------------------
+# some constants
+#
+xmake_sh_projectdir=$(X= cd -- "$(dirname -- "$0")" && pwd -P)
+xmake_sh_buildir="build"
+xmake_sh_version="1.0.3"
+xmake_sh_verbose=false
+xmake_sh_diagnosis=false
+xmake_sh_copyright="Copyright (C) 2022-present Ruki Wang, tboox.org, xmake.io."
+xmake_sh_makefile="${xmake_sh_projectdir}/makefile"
+
+#-----------------------------------------------------------------------------
+# some helper functions
+#
+raise() {
+ echo "$@" 1>&2 ; exit 1
+}
+
+vprint() {
+ if "${xmake_sh_verbose}"; then
+ echo "$@"
+ fi
+}
+
+dprint() {
+ if "${xmake_sh_diagnosis}"; then
+ echo "$@"
+ fi
+}
+
+# show and escape string instead of `echo -e`, because sh does not support it
+print() {
+ printf "${@}\n"
+}
+
+# test empty string
+test_z() {
+ if test "x${1}" = "x"; then
+ return 0
+ fi
+ return 1
+}
+
+# test non-empty string
+test_nz() {
+ if test "x${1}" != "x"; then
+ return 0
+ fi
+ return 1
+}
+
+# test string is equal
+test_eq() {
+ if test "x${1}" = "x${2}"; then
+ return 0
+ fi
+ return 1
+}
+
+# test string is not equal
+test_nq() {
+ if test "x${1}" != "x${2}"; then
+ return 0
+ fi
+ return 1
+}
+
+string_toupper() {
+ _ret=$(echo "$1" | tr '[a-z]' '[A-Z]')
+}
+
+string_tolower() {
+ _ret=$(echo "$1" | tr '[A-Z]' '[a-z]')
+}
+
+string_replace() {
+ _ret=$(echo "$1" | sed "s/${2}/${3}/g")
+}
+
+# we avoid use `cut` command, because it's slow
+string_split() {
+ local str="${1}"
+ local sep="${2}"
+ local idx="${3}"
+ local oldifs="${IFS}"
+ IFS="${sep}"
+ set -- ${str}
+ if test_nz "${idx}"; then
+ case "${idx}" in
+ 1) _ret="$1";;
+ 2) _ret="$2";;
+ 3) _ret="$3";;
+ esac
+ else
+ _ret="$1"
+ _ret2="$2"
+ _ret3="$3"
+ fi
+ IFS="${oldifs}"
+}
+
+# does contain sub-string?
+# e.g.
+# str="src/*.cpp"
+# string_contains "$str" "src"
+string_contains() {
+ case "${1}" in
+ *${2}*) return 0;;
+ *) return 1;;
+ esac
+ return 1
+}
+
+# does contain "*"?
+string_contains_star() {
+ case "${1}" in
+ *\**) return 0;; # bash
+ *'*'*) return 0;; # csh
+ *) return 1;;
+ esac
+ return 1
+}
+
+# does contain "**"?
+string_contains_star2() {
+ case "${1}" in
+ *\*\**) return 0;; # bash
+ *'**'*) return 0;; # csh
+ *) return 1;;
+ esac
+ return 1
+}
+
+# does startswith sub-string?
+# e.g.
+# str="src/*.cpp"
+# string_startswith "$str" "src"
+string_startswith() {
+ case "${1}" in
+ ${2}*) return 0;;
+ *) return 1;;
+ esac
+ return 1
+}
+
+# duplicate characters
+# e.g. string_dupch 10 "." => ...........
+string_dupch() {
+ local count=${1}
+ local ch=${2}
+ printf %${count}s | tr " " "${ch}"
+}
+
+# replace file content
+_io_replace_file() {
+ local infile="${1}"
+ local outfile="${2}"
+ local patterns="${3}"
+ sed "/./ {${patterns}}" "${infile}" > "${outfile}"
+}
+
+# try remove file or directory
+_os_tryrm() {
+ if test -f "${1}"; then
+ rm "${1}"
+ elif test -d "${1}"; then
+ rm -r "${1}"
+ fi
+}
+
+# get temporary file
+_os_tmpfile() {
+ _ret=$(mktemp)
+}
+
+# try run program
+_os_runv() {
+ local cmd="${@}"
+ if ${xmake_sh_diagnosis}; then
+ ${cmd}
+ else
+ ${cmd} >/dev/null 2>&1
+ fi
+ local ok=$?
+ if test "${ok}" -ne "0"; then
+ return 1
+ fi
+ return 0
+}
+
+# try run program and get output
+_os_iorunv() {
+ local cmd="${@}"
+ _os_tmpfile
+ local tmpfile="${_ret}"
+ ${cmd} >"${tmpfile}" 2>&1
+ local ok=$?
+ if test "${ok}" -ne "0"; then
+ _ret=""
+ else
+ local result=$(cat "${tmpfile}")
+ _ret="${result}"
+ fi
+ _os_tryrm "${tmpfile}"
+}
+
+# find file in the given directory
+# e.g. _os_find . xmake.sh
+_os_find() {
+ local dir="${1}"
+ local name="${2}"
+ local depth="${3}"
+ if test_nz "${depth}"; then
+ if is_host "macosx"; then
+ _ret=$(find "${dir}" -depth "${depth}" -name "${name}")
+ else
+ _ret=$(find "${dir}" -maxdepth "${depth}" -mindepth "${depth}" -name "${name}")
+ fi
+ else
+ _ret=$(find "${dir}" -name "${name}")
+ fi
+}
+
+# get date, "%Y%m%d%H%M" -> 202212072222
+_os_date() {
+ _ret=$(date +"${1}")
+}
+
+# we avoid use `basename`, because it's slow
+path_filename() {
+ local path="${1}"
+ local oldifs="${IFS}"
+ IFS='/'
+ set -- ${path}
+ local filename=""
+ for item in $@; do
+ filename="$item"
+ done
+ _ret="${filename}"
+ IFS="${oldifs}"
+}
+
+path_extension() {
+ path_filename "${1}"; local filename="${_ret}"
+ _ret=".${filename##*.}"
+}
+
+path_basename() {
+ path_filename "${1}"; local filename="${_ret}"
+ _ret="${filename%.*}"
+}
+
+# we avoid use `dirname -- ${1}`, because it's too slow
+path_directory() {
+ local path="${1}"
+ local oldifs="${IFS}"
+ IFS='/'
+ set -- ${path}
+ local dir=""
+ local first=true
+ local startswith_sep=false
+ while test $# != 1; do
+ local item="${1}"
+ if test_nz "${item}"; then
+ dir="${dir}/${item}"
+ elif $first; then
+ startswith_sep=true
+ fi
+ first=false
+ shift
+ done
+ if $startswith_sep; then
+ if test_z "${dir}"; then
+ dir="/"
+ fi
+ else
+ dir="${dir#/}"
+ if test_z "${dir}"; then
+ dir="."
+ fi
+ fi
+ _ret="${dir}"
+ IFS="${oldifs}"
+}
+
+# e.g. path_filename_fromdir "/tmp/file" "/tmp" -> "file"
+path_filename_fromdir() {
+ _ret="${1#${2}/}"
+}
+
+path_is_absolute() {
+ if string_startswith "${1}" "/"; then
+ return 0
+ fi
+ return 1
+}
+
+# get relative path, e.g $(path_relative ${rootdir} ${absolute_path}`
+path_relative() {
+ local source=$1
+ local target=$2
+
+ local common_part=$source
+ local result=""
+
+ while test_eq "${target#$common_part}" "${target}"; do
+ # no match, means that candidate common part is not correct
+ # go up one level (reduce common part)
+ path_directory "${common_part}"; common_part="${_ret}"
+ # and record that we went back, with correct / handling
+ if test_z $result; then
+ result=".."
+ else
+ result="../$result"
+ fi
+ done
+
+ if test_eq $common_part "/"; then
+ # special case for root (no common path)
+ result="$result/"
+ fi
+
+ # since we now have identified the common part,
+ # compute the non-common part
+ local forward_part="${target#$common_part}"
+
+ # and now stick all parts together
+ if test_nz $result && test_nz $forward_part; then
+ result="$result$forward_part"
+ elif test_nz $forward_part; then
+ # remote extra '/', e.g. "/xxx" => "xxx"
+ result="${forward_part#*/}"
+ fi
+
+ _ret="$result"
+}
+
+path_sourcekind() {
+ local sourcekind=""
+ case "${1}" in
+ *.cpp) sourcekind="cxx";;
+ *.cc) sourcekind="cxx";;
+ *.c) sourcekind="cc";;
+ *.ixx) sourcekind="cxx";;
+ *.mm) sourcekind="mxx";;
+ *.m) sourcekind="mm";;
+ *.S) sourcekind="as";;
+ *.s) sourcekind="as";;
+ *.asm) sourcekind="as";;
+ *) raise "unknown sourcekind for ${1}" ;;
+ esac
+ _ret="${sourcekind}"
+}
+
+path_toolname() {
+ local toolname=""
+ case "${1}" in
+ *-gcc) toolname="gcc";;
+ */gcc) toolname="gcc";;
+ gcc) toolname="gcc";;
+ *-g++) toolname="gxx";;
+ */g++) toolname="gxx";;
+ g++) toolname="gxx";;
+ xcrun*clang++) toolname="clangxx";;
+ xcrun*clang) toolname="clang";;
+ *-clang++) toolname="clangxx";;
+ */clang++) toolname="clangxx";;
+ clang++) toolname="clangxx";;
+ *-clang) toolname="clang";;
+ */clang) toolname="clang";;
+ clang) toolname="clang";;
+ *-ar) toolname="ar";;
+ */ar) toolname="ar";;
+ ar) toolname="ar";;
+ *) raise "unknown tool ${1}";;
+ esac
+ _ret="${toolname}"
+}
+
+# get flag name from toolkind, e.g. cc => cflags, cxx => cxxflags
+_get_flagname() {
+ local toolkind="${1}"
+ local flagname=""
+ case "${toolkind}" in
+ cc) flagname="cflags";;
+ cxx) flagname="cxxflags";;
+ as) flagname="asflags";;
+ mm) flagname="mflags";;
+ mxx) flagname="mxxflags";;
+ ar) flagname="arflags";;
+ sh) flagname="shflags";;
+ ld) flagname="ldflags";;
+ *) raise "unknown toolkind(${toolkind})!" ;;
+ esac
+ _ret="${flagname}"
+}
+
+# is enabled? true, yes, y
+_is_enabled() {
+ local value=${1}
+ if test_eq "${value}" "true"; then
+ return 0
+ elif test_eq "${value}" "yes"; then
+ return 0
+ elif test_eq "${value}" "y"; then
+ return 0
+ fi
+ return 1
+}
+
+# deduplicate string list
+# .e.g "hello world hello how are you world" -> hello world how are you
+_dedup() {
+ _ret=$(echo "${1}" | awk '{for (i = 1; i <= NF; ++i) if (!seen[$i]++) printf $i " "}')
+}
+
+# deduplicate string list from the reverse order
+# .e.g "hello world hello how are you world" -> hello how are you world
+_dedup_reverse() {
+ local result=""
+ local list=$(echo "${1}" | awk '{for (i = NF; i > 0; --i) if (!seen[$i]++) printf $i " "}')
+ local item=""
+ for item in ${list}; do
+ result="${item} ${result}"
+ done
+ _ret="${result}"
+}
+
+#-----------------------------------------------------------------------------
+# map functions
+#
+
+# define map, @note we can not use bash/declare to define map, because sh does not support it.
+#
+# _map "options"
+# _map_set "options" "key1" "value1"
+# _map_set "options" "key2" "value2"
+# _map_set "options" "key2" "value3"
+# _map_set "options" "key3" "value3"
+# _map_set "options" "key4" "__empty__"
+# _map_set "options" "key4" "__empty__"
+# _map_count "options"; _count="${_ret}"
+# _map_keys "options"; _keys="${_ret}"
+# echo ${_count}
+# for key in ${_keys}; do
+# _map_get "options" ${key}; value="{_ret}"
+# echo ${key} "->" ${value}
+# done
+#
+# echo "------"
+# _map_remove "options" "key3"
+# _map_count "options"; _count="${_ret}"
+# _map_keys "options"; _keys="${_ret}"
+# echo ${_count}
+# for key in ${_keys}; do
+# _map_get "options" ${key}; value="{_ret}"
+# echo ${key} "->" ${value}
+# done
+#
+_map() {
+ local name=${1}
+# eval _map_${name}_count=0
+# eval _map_${name}_keys=""
+}
+
+# because the shell is slow, we have to temporarily
+# disable some of the map features for performance.
+#
+#_map_count() {
+# local name=${1}
+# local count=$(eval echo \$_map_${name}_count)
+# _ret="${count}"
+#}
+
+_map_get() {
+ local name=${1}
+ local key=${2}
+ local value=$(eval echo \$_map_${name}_value_${key})
+ if test_eq "${value}" "__empty__"; then
+ value=""
+ fi
+ _ret="${value}"
+}
+
+_map_has() {
+ local name=${1}
+ local key=${2}
+ local value=$(eval echo \$_map_${name}_value_${key})
+ if test_nz "${value}"; then
+ return 0
+ fi
+ return 1
+}
+
+_map_set() {
+ local name=${1}
+ local key=${2}
+ local value=${3}
+# if ! _map_has ${name} ${key}; then
+# _map_count "options"; local count="${_ret}"
+# eval _map_${name}_count=$((${count} + 1))
+# local keys=$(eval echo \$_map_${name}_keys)
+# keys="${keys} ${key}"
+# eval _map_${name}_keys=\${keys}
+# fi
+ eval _map_${name}_value_${key}=\${value}
+}
+
+#_map_remove() {
+# local name=${1}
+# local key=${2}
+# if _map_has ${name} ${key}; then
+# _map_count "options"; local count="${_ret}"
+# eval _map_${name}_count=$((${count} - 1))
+# eval _map_${name}_value_${key}=""
+# local keys=$(eval echo \$_map_${name}_keys)
+# local keys_new=""
+# local k=""
+# for k in ${keys}; do
+# if test_nq "${k}" "${key}"; then
+# keys_new="${keys_new} ${k}"
+# fi
+# done
+# eval _map_${name}_keys=\${keys_new}
+# fi
+#}
+
+#_map_keys() {
+# local name=${1}
+# local keys=$(eval echo \$_map_${name}_keys)
+# _ret="${keys}"
+#}
+
+#-----------------------------------------------------------------------------
+# detect default environments
+#
+
+# detect hosts
+os_host=`uname`
+string_tolower ${os_host}; os_host="${_ret}"
+if echo "${os_host}" | grep cygwin >/dev/null 2>&1; then
+ os_host="cygwin"
+fi
+if echo "${os_host}" | grep msys >/dev/null 2>&1; then
+ os_host="msys"
+fi
+if echo "${os_host}" | grep mingw >/dev/null 2>&1; then
+ os_host="msys"
+fi
+if echo "${os_host}" | grep darwin >/dev/null 2>&1; then
+ os_host="macosx"
+fi
+if echo "${os_host}" | grep linux >/dev/null 2>&1; then
+ os_host="linux"
+fi
+if echo "${os_host}" | grep freebsd >/dev/null 2>&1; then
+ os_host="freebsd"
+fi
+if echo "${os_host}" | grep bsd >/dev/null 2>&1; then
+ os_host="bsd"
+fi
+
+# determining host
+# e.g.
+# if is_host "linux" "macosx"; then
+# ...
+# fi
+is_host() {
+ local host=""
+ for host in $@; do
+ if test_eq "${os_host}" "${host}"; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+# detect host architecture
+os_arch=`uname -m | tr '[A-Z]' '[a-z]'`
+if test_eq "${os_arch}" "i686"; then
+ os_arch="i386"
+fi
+
+# set the default target platform and architecture
+_target_plat_default=${os_host}
+if is_host "msys"; then
+ _target_plat_default="mingw"
+fi
+_target_arch_default=${os_arch}
+_target_mode_default="release"
+
+# set the default project generator and build program
+if is_host "freebsd" "bsd"; then
+ _project_generator="gmake"
+ _make_program_default="gmake"
+ _ninja_program_default="ninja"
+elif is_host "msys" "cygwin"; then
+ _project_generator="gmake"
+ _make_program_default="make.exe"
+ _ninja_program_default="ninja.exe"
+else
+ _project_generator="gmake"
+ _make_program_default="make"
+ _ninja_program_default="ninja"
+fi
+
+# set the default directories
+if test -d "/usr/local"; then
+ _install_prefix_default="/usr/local"
+elif test -d "/usr"; then
+ _install_prefix_default="/usr"
+fi
+_install_bindir_default="bin"
+_install_libdir_default="lib"
+_install_includedir_default="include"
+
+# determining target platform
+# e.g.
+# if is_plat "linux" "macosx"; then
+# ...
+# fi
+is_plat() {
+ local plat=""
+ for plat in $@; do
+ if test_eq "${_target_plat}" "${plat}"; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+# determining target architecture
+# e.g.
+# if is_arch "x86_64" "i386"; then
+# ...
+# fi
+is_arch() {
+ local arch=""
+ for arch in $@; do
+ if test_eq "${_target_arch}" "${arch}"; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+# determining target mode
+# e.g.
+# if is_mode "release"; then
+# ...
+# fi
+is_mode() {
+ local mode=""
+ for mode in $@; do
+ if test_eq "${_target_mode}" "${mode}"; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+# determining target toolchain
+# e.g.
+# if is_toolchain "clang"; then
+# ...
+# fi
+is_toolchain() {
+ local toolchain=""
+ for toolchain in $@; do
+ if test_eq "${_target_toolchain}" "${toolchain}"; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+#-----------------------------------------------------------------------------
+# project configuration apis
+#
+
+# set project name
+set_project() {
+ _xmake_sh_project_name="${1}"
+}
+
+# include the given xmake.sh file or directory
+# e.g. includes "src" "tests"
+includes() {
+ local path=""
+ for path in $@; do
+ if test -f "${path}"; then
+ path_directory "${path}"; xmake_sh_scriptdir="${_ret}"
+ . "${path}"
+ else
+ local xmake_sh_scriptdir_cur=${xmake_sh_scriptdir}
+ if test "x${xmake_sh_scriptdir}" != "x"; then
+ xmake_sh_scriptdir="${xmake_sh_scriptdir_cur}/${path}"
+ . "${xmake_sh_scriptdir}/xmake.sh"
+ else
+ . "${xmake_sh_projectdir}/${path}/xmake.sh"
+ fi
+ xmake_sh_scriptdir=${xmake_sh_scriptdir_cur}
+ fi
+ done
+}
+
+#-----------------------------------------------------------------------------
+# some helper functions
+#
+
+# split flags
+_split_flags() {
+ string_replace "${1}" ":" " "
+}
+
+# get abstract flag for gcc/clang
+_get_abstract_flag_for_gcc_clang() {
+ local toolkind="${1}"
+ local toolname="${2}"
+ local itemname="${3}"
+ local value="${4}"
+ local flag=""
+ case "${itemname}" in
+ defines)
+ string_replace "${value}" '"' '\\\"'; value="${_ret}"
+ flag="-D${value}"
+ ;;
+ udefines) flag="-U${value}";;
+ includedirs) flag="-I${value}";;
+ linkdirs) flag="-L${value}";;
+ links) flag="-l${value}";;
+ syslinks) flag="-l${value}";;
+ frameworks) flag="-framework ${value}";;
+ frameworkdirs) flag="-F${value}";;
+ rpathdirs)
+ if test_eq "${toolname}" "gcc" || test_eq "${toolname}" "gxx"; then
+ # escape $ORIGIN in makefile, TODO we need also handle it for ninja
+ string_replace "${value}" "@loader_path" '$$ORIGIN'; value="${_ret}"
+ flag="-Wl,-rpath='${value}'"
+ elif test_eq "${toolname}" "clang" || test_eq "${toolname}" "clangxx"; then
+ string_replace "${value}" "\$ORIGIN" "@loader_path"; value="${_ret}"
+ flag="-Xlinker -rpath -Xlinker ${value}"
+ fi
+ ;;
+ symbols)
+ if test_eq "${value}" "debug"; then
+ flag="-g"
+ elif test_eq "${value}" "hidden"; then
+ flag="-fvisibility=hidden"
+ fi
+ ;;
+ strip)
+ if test_eq "${value}" "debug"; then
+ flag="-Wl,-S"
+ elif test_eq "${value}" "all"; then
+ if is_plat "macosx"; then
+ flag="-Wl,-x"
+ else
+ flag="-s"
+ fi
+ fi
+ ;;
+ warnings)
+ if test_eq "${value}" "all" || test_eq "${value}" "more" || test_eq "${value}" "less"; then
+ flag="-Wall"
+ elif test_eq "${value}" "allextra"; then
+ flag="-Wall -Wextra"
+ elif test_eq "${value}" "error"; then
+ flag="-Werror"
+ elif test_eq "${value}" "everything"; then
+ flag="-Wall -Wextra"
+ elif test_eq "${value}" "none"; then
+ flag="-w"
+ fi
+ ;;
+ optimizes)
+ if test_eq "${value}" "fast"; then
+ flag="-O1"
+ elif test_eq "${value}" "faster"; then
+ flag="-O2"
+ elif test_eq "${value}" "fastest"; then
+ flag="-O3"
+ elif test_eq "${value}" "smallest"; then
+ if test_eq "${toolname}" "clang" || test_eq "${toolname}" "clangxx"; then
+ flag="-Oz"
+ else
+ flag="-Os"
+ fi
+ elif test_eq "${value}" "aggressive"; then
+ flag="-Ofast"
+ elif test_eq "${value}" "none"; then
+ flag="-O0"
+ fi
+ ;;
+ languages)
+ if test_eq "${toolkind}" "cc" || test_eq "${toolkind}" "mm"; then
+ case "${value}" in
+ ansi) flag="-ansi";;
+ c89) flag="-std=c89";;
+ gnu89) flag="-std=gnu89";;
+ c99) flag="-std=c99";;
+ gnu99) flag="-std=gnu99";;
+ c11) flag="-std=c11";;
+ gnu11) flag="-std=gnu11";;
+ c17) flag="-std=c17";;
+ gnu17) flag="-std=gnu17";;
+ esac
+ elif test_eq "${toolkind}" "cxx" || test_eq "${toolkind}" "mxx"; then
+ case "${value}" in
+ cxx98) flag="-std=c++98";;
+ c++98) flag="-std=c++98";;
+ gnuxx98) flag="-std=gnu++98";;
+ gnu++98) flag="-std=gnu++98";;
+
+ cxx11) flag="-std=c++11";;
+ c++11) flag="-std=c++11";;
+ gnuxx11) flag="-std=gnu++11";;
+ gnu++11) flag="-std=gnu++11";;
+
+ cxx14) flag="-std=c++14";;
+ c++14) flag="-std=c++14";;
+ gnuxx14) flag="-std=gnu++14";;
+ gnu++14) flag="-std=gnu++14";;
+
+ cxx17) flag="-std=c++17";;
+ c++17) flag="-std=c++17";;
+ gnuxx17) flag="-std=gnu++17";;
+ gnu++17) flag="-std=gnu++17";;
+
+ cxx1z) flag="-std=c++1z";;
+ c++1z) flag="-std=c++1z";;
+ gnuxx1z) flag="-std=gnu++1z";;
+ gnu++1z) flag="-std=gnu++1z";;
+
+ cxx2a) flag="-std=c++2a";;
+ c++2a) flag="-std=c++2a";;
+ gnuxx2a) flag="-std=gnu++2a";;
+ gnu++2a) flag="-std=gnu++2a";;
+
+ cxx20) flag="-std=c++20";;
+ c++20) flag="-std=c++20";;
+ gnuxx20) flag="-std=gnu++20";;
+ gnu++20) flag="-std=gnu++20";;
+ cxx*) raise "unknown language value(${value})!" ;;
+ c++*) raise "unknown language value(${value})!" ;;
+ esac
+ fi
+ ;;
+ *) raise "unknown itemname(${itemname})!" ;;
+ esac
+ _ret="${flag}"
+}
+
+# get abstract flags
+_get_abstract_flags() {
+ local toolkind="${1}"
+ local toolname="${2}"
+ local itemname="${3}"
+ local values="${4}"
+ local flags=""
+ local value=""
+ for value in ${values}; do
+ local flag=""
+ case "${toolname}" in
+ gcc) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
+ gxx) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
+ clang) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
+ clangxx) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
+ *) raise "unknown toolname(${toolname})!" ;;
+ esac
+ if test_nz "${flag}"; then
+ flags="${flags} ${flag}"
+ fi
+ done
+ _ret="${flags}"
+}
+
+#-----------------------------------------------------------------------------
+# option configuration apis
+#
+
+# define option
+option() {
+ local name="${1}"
+ local description="${2}"
+ local default=${3}
+ _xmake_sh_option_current="${name}"
+ if ! ${_loading_options}; then
+ if test_nz "${description}"; then
+ _xmake_sh_option_current=""
+ fi
+ return
+ fi
+ _xmake_sh_options="${_xmake_sh_options} ${name}"
+ _map_set "options" "${name}_name" "${name}"
+ _map_set "options" "${name}_description" "${description}"
+ _map_set "options" "${name}_default" "${default}"
+ # we end option if it's just one line
+ if test_nz "${description}"; then
+ _xmake_sh_option_current=""
+ fi
+ return 0
+}
+option_end() {
+ _xmake_sh_option_current=""
+}
+_map "options"
+
+# has the given option?
+_has_option() {
+ local name=${1}
+ if _map_has "options" "${name}_name"; then
+ return 0
+ fi
+ return 1
+}
+
+# get the given option item
+_get_option_item() {
+ local name=${1}
+ local key=${2}
+ _map_get "options" "${name}_${key}"
+}
+
+# set the given option item
+_set_option_item() {
+ local name=${1}
+ local key=${2}
+ local value=${3}
+ if test_nz "${name}"; then
+ _map_set "options" "${name}_${key}" "${value}"
+ else
+ raise "please call set_${key}(${value}) in the option scope!"
+ fi
+}
+
+# add values to the given option item
+_add_option_item() {
+ local name=${1}
+ local key=${2}
+ local value=${3}
+ if test_nz "${name}"; then
+ _map_get "options" "${name}_${key}"; local values="${_ret}"
+ values="${values} ${value}"
+ _map_set "options" "${name}_${key}" "${values}"
+ else
+ raise "please call add_${key}(${value}) in the option scope!"
+ fi
+}
+
+# get the give option value
+_get_option_value() {
+ local name=${1}
+ _get_option_item "${name}" "value"
+ if test "x${_ret}" = "x"; then
+ _get_option_item "${name}" "default"
+ fi
+}
+
+# set the give option value
+_set_option_value() {
+ local name=${1}
+ local value=${2}
+ _set_option_item "${name}" "value" "${value}"
+}
+
+# this option need checking?
+_option_need_checking() {
+ local name="${1}"
+ _get_option_item "${name}" "default"; local default="${_ret}"
+ if test_nz "${default}"; then
+ return 1
+ fi
+ _get_option_item "${name}" "cfuncs"; local cfuncs="${_ret}"
+ _get_option_item "${name}" "cxxfuncs"; local cxxfuncs="${_ret}"
+ _get_option_item "${name}" "cincludes"; local cincludes="${_ret}"
+ _get_option_item "${name}" "cxxincludes"; local cxxincludes="${_ret}"
+ _get_option_item "${name}" "ctypes"; local ctypes="${_ret}"
+ _get_option_item "${name}" "cxxtypes"; local cxxtypes="${_ret}"
+ _get_option_item "${name}" "csnippets"; local csnippets="${_ret}"
+ _get_option_item "${name}" "cxxsnippets"; local cxxsnippets="${_ret}"
+ _get_option_item "${name}" "links"; local links="${_ret}"
+ _get_option_item "${name}" "syslinks"; local syslinks="${_ret}"
+ if test_nz "${cfuncs}" || test_nz "${cxxfuncs}" ||
+ test_nz "${cincludes}" || test_nz "${cxxincludes}" ||
+ test_nz "${ctypes}" || test_nz "${cxxtypes}" ||
+ test_nz "${csnippets}" || test_nz "${cxxsnippets}" ||
+ test_nz "${links}" || test_nz "${syslinks}"; then
+ return 0
+ fi
+ return 1
+}
+
+# get options for the help menu
+_get_options_for_menu() {
+ local options=""
+ local name=""
+ for name in ${_xmake_sh_options}; do
+ _get_option_item "${name}" "showmenu"; local showmenu="${_ret}"
+ if _is_enabled "${showmenu}"; then
+ options="${options} ${name}"
+ elif test_z "${showmenu}" && ! _option_need_checking "${name}"; then
+ options="${options} ${name}"
+ fi
+ done
+ _ret="${options}"
+}
+
+# get options for checking
+_get_options_for_checking() {
+ local options=""
+ local name=""
+ for name in ${_xmake_sh_options}; do
+ _get_option_item "${name}" "showmenu"; local showmenu="${_ret}"
+ if test_z "${showmenu}" && _option_need_checking "${name}"; then
+ options="${options} ${name}"
+ fi
+ done
+ _ret="${options}"
+}
+
+# get abstract flags in option
+_get_option_abstract_flags() {
+ local name="${1}"
+ local toolkind="${2}"
+ local toolname="${3}"
+ local itemname="${4}"
+ local values="${5}"
+ if test_z "${values}"; then
+ _get_option_item "${name}" "${itemname}"; values="${_ret}"
+ fi
+ _get_abstract_flags "${toolkind}" "${toolname}" "${itemname}" "${values}"
+}
+
+# is config for option
+is_config() {
+ if ! ${_loading_targets}; then
+ return 1
+ fi
+ local name=${1}
+ local value=${2}
+ _get_option_value "${name}"; local value_cur="${_ret}"
+ if test_eq "${value_cur}" "${value}"; then
+ return 0
+ fi
+ return 1
+}
+
+# has config for option
+has_config() {
+ if ! ${_loading_targets}; then
+ return 1
+ fi
+ local name=${1}
+ _get_option_value "${name}"; local value_cur="${_ret}"
+ if _is_enabled ${value_cur}; then
+ return 0
+ fi
+ return 1
+}
+
+# set config for option, we can use it to modify option status when loading targets
+set_config() {
+ local name=${1}
+ local value=${2}
+ _set_option_value "${name}" "${value}"
+}
+
+# set showmenu in option
+set_showmenu() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local show="${1}"
+ _set_option_item "${_xmake_sh_option_current}" "showmenu" "${show}"
+}
+
+# set description in option
+set_description() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local description="${1}"
+ _set_option_item "${_xmake_sh_option_current}" "description" "${description}"
+}
+
+# add cfuncs in option
+add_cfuncs() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local cfuncs="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "cfuncs" "${cfuncs}"
+}
+
+# add cxxfuncs in option
+add_cxxfuncs() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local cxxfuncs="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "cxxfuncs" "${cxxfuncs}"
+}
+
+# add cincludes in option
+add_cincludes() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local cincludes="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "cincludes" "${cincludes}"
+}
+
+# add cxxincludes in option
+add_cxxincludes() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local cxxincludes="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "cxxincludes" "${cxxincludes}"
+}
+
+# add ctypes in option
+add_ctypes() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local ctypes="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "ctypes" "${ctypes}"
+}
+
+# add cxxtypes in option
+add_cxxtypes() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local cxxtypes="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "cxxtypes" "${cxxtypes}"
+}
+
+# add csnippets in option
+add_csnippets() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local csnippets="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "csnippets" "${csnippets}"
+}
+
+# add cxxsnippets in option
+add_cxxsnippets() {
+ if ! ${_loading_options}; then
+ return
+ fi
+ local cxxsnippets="${1}"
+ _add_option_item "${_xmake_sh_option_current}" "cxxsnippets" "${cxxsnippets}"
+}
+
+#-----------------------------------------------------------------------------
+# target configuration apis
+#
+
+# define target
+target() {
+ local name="${1}"
+ _xmake_sh_target_current="${name}"
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _xmake_sh_targets="${_xmake_sh_targets} ${name}"
+ _map_set "targets" "${name}_name" "${name}"
+ return 0
+}
+target_end() {
+ _xmake_sh_target_current=""
+}
+_map "targets"
+
+# has the given target?
+_has_target() {
+ local name=${1}
+ if _map_has "targets" "${name}_name"; then
+ return 0
+ fi
+ return 1
+}
+
+# has the given target item
+_has_target_item() {
+ local name=${1}
+ local key=${2}
+ if _map_has "targets" "${name}_${key}"; then
+ return 0
+ elif _map_has "targets" "__root_${key}"; then
+ return 0
+ fi
+ return 1
+}
+
+# get the given target item
+_get_target_item() {
+ local name=${1}
+ local key=${2}
+ _map_get "targets" "${name}_${key}"
+ local values="${_ret}"
+ if _map_has "targets" "__root_${key}"; then
+ _map_get "targets" "__root_${key}"; local root_values="${_ret}"
+ if test_nz "${values}"; then
+ values="${root_values} ${values}"
+ else
+ values="${root_values}"
+ fi
+ fi
+ _ret="${values}"
+}
+
+# set the given target item
+_set_target_item() {
+ local name=${1}
+ local key=${2}
+ local value=${3}
+ if test_nz "${name}"; then
+ _map_set "targets" "${name}_${key}" "${value}"
+ else
+ _map_set "targets" "__root_${key}" "${value}"
+ fi
+}
+
+# add values to the given target item
+_add_target_item() {
+ local name=${1}
+ local key=${2}
+ local value=${3}
+ if test_nz "${name}"; then
+ _map_get "targets" "${name}_${key}"; local values="${_ret}"
+ values="${values} ${value}"
+ _map_set "targets" "${name}_${key}" "${values}"
+ else
+ _map_get "targets" "__root_${key}"; local values="${_ret}"
+ values="${values} ${value}"
+ _map_set "targets" "__root_${key}" "${values}"
+ fi
+}
+
+# is default?
+_is_target_default() {
+ local name="${1}"
+ if _has_target_item "${name}" "default"; then
+ _get_target_item "${target}" "default"; local default="${_ret}"
+ if _is_enabled ${default}; then
+ return 0
+ fi
+ return 1
+ fi
+ return 0
+}
+
+# get target basename
+_get_target_basename() {
+ local name="${1}"
+ _get_target_item "${name}" "basename"; local basename="${_ret}"
+ if test_z "${basename}"; then
+ basename="${name}"
+ fi
+ _ret="${basename}"
+}
+
+# get target extension
+_get_target_extension() {
+ local name="${1}"
+ local extension=""
+ if _has_target_item "${name}" "extension"; then
+ _get_target_item "${name}" "extension"; extension="${_ret}"
+ elif is_plat "mingw"; then
+ _get_target_item "${name}" "kind"; local kind="${_ret}"
+ if test "x${kind}" = "xbinary"; then
+ extension=".exe"
+ elif test "x${kind}" = "xstatic"; then
+ extension=".a"
+ elif test "x${kind}" = "xshared"; then
+ extension=".dll"
+ fi
+ else
+ _get_target_item "${name}" "kind"; local kind="${_ret}"
+ if test "x${kind}" = "xstatic"; then
+ extension=".a"
+ elif test "x${kind}" = "xshared"; then
+ extension=".so"
+ fi
+ fi
+ _ret="${extension}"
+}
+
+# get target prefixname
+_get_target_prefixname() {
+ local name="${1}"
+ local prefixname=""
+ if _has_target_item "${name}" "prefixname"; then
+ _get_target_item "${name}" "prefixname"; prefixname="${_ret}"
+ elif is_plat "mingw"; then
+ _get_target_item "${name}" "kind"; local kind="${_ret}"
+ if test "x${kind}" = "xstatic"; then
+ prefixname="lib"
+ elif test "x${kind}" = "xshared"; then
+ prefixname="lib"
+ fi
+ else
+ _get_target_item "${name}" "kind"; local kind="${_ret}"
+ if test "x${kind}" = "xstatic"; then
+ prefixname="lib"
+ elif test "x${kind}" = "xshared"; then
+ prefixname="lib"
+ fi
+ fi
+ _ret="${prefixname}"
+}
+
+# get target filename
+_get_target_filename() {
+ local name="${1}"
+ _get_target_item "${name}" "filename"; local filename="${_ret}"
+ if test_z "${filename}"; then
+ _get_target_basename "${name}"; local basename="${_ret}"
+ _get_target_extension "${name}"; local extension="${_ret}"
+ _get_target_prefixname "${name}"; local prefixname="${_ret}"
+ filename="${prefixname}${basename}${extension}"
+ fi
+ _ret="${filename}"
+}
+
+# get target directory
+_get_targetdir() {
+ local name="${1}"
+ _get_target_item "${name}" "targetdir"; local targetdir="${_ret}"
+ if test_z "${targetdir}"; then
+ targetdir="${xmake_sh_buildir}/${_target_plat}/${_target_arch}/${_target_mode}"
+ fi
+ _ret="${targetdir}"
+}
+
+# get target object directory
+_get_target_objectdir() {
+ local name="${1}"
+ _get_target_item "${name}" "objectdir"; local objectdir="${_ret}"
+ if test_z "${objectdir}"; then
+ objectdir="${xmake_sh_buildir}/.objs/${name}/${_target_plat}/${_target_arch}/${_target_mode}"
+ fi
+ _ret="${objectdir}"
+}
+
+# get target file path
+_get_target_file() {
+ local name="${1}"
+ _get_target_filename "${name}"; local filename="${_ret}"
+ _get_targetdir "${name}"; local targetdir="${_ret}"
+ local targetfile="${targetdir}/${filename}"
+ _ret="${targetfile}"
+}
+
+# get target librarydeps
+_get_target_librarydeps_impl() {
+ local name="${1}"
+ local librarydeps=""
+ local dep=""
+ _get_target_item "${name}" "deps"; local deps="${_ret}"
+ for dep in ${deps}; do
+ _get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
+ if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
+ librarydeps="${librarydeps} ${dep}"
+ _get_target_librarydeps_impl "${dep}"; local dep_librarydeps="${_ret}"
+ if test_nz "${dep_librarydeps}"; then
+ librarydeps="${librarydeps} ${dep_librarydeps}"
+ fi
+ fi
+ done
+ _ret="${librarydeps}"
+}
+
+_get_target_librarydeps() {
+ local name="${1}"
+ _get_target_item "${name}" "librarydeps"; local librarydeps="${_ret}"
+ if test_z "${librarydeps}" && test_nq "${librarydeps}" "__none__"; then
+ _get_target_librarydeps_impl "${name}"; librarydeps="${_ret}"
+ if test_nz "${librarydeps}"; then
+ _dedup_reverse "${librarydeps}"; librarydeps="${_ret}"
+ _set_target_item "${name}" "librarydeps" "${librarydeps}"
+ else
+ _set_target_item "${name}" "librarydeps" "__none__"
+ fi
+ fi
+ if test_eq "${librarydeps}" "__none__"; then
+ librarydeps=""
+ fi
+ _ret="${librarydeps}"
+}
+
+# get sourcefiles in target
+_get_target_sourcefiles() {
+ local name="${1}"
+ _get_target_item "${name}" "files"
+}
+
+# get objectfile in target
+_get_target_objectfile() {
+ local name="${1}"
+ local sourcefile="${2}"
+ local extension=".o"
+ if is_plat "mingw"; then
+ extension=".obj"
+ fi
+ _get_target_objectdir "${name}"; local objectdir="${_ret}"
+ local objectfile="${objectdir}/${sourcefile}${extension}"
+ _ret="${objectfile}"
+}
+
+# get objectfiles in target
+_get_target_objectfiles() {
+ local name="${1}"
+ _get_target_sourcefiles "${name}"; local sourcefiles="${_ret}"
+ local objectfiles=""
+ local sourcefile=""
+ for sourcefile in ${sourcefiles}; do
+ _get_target_objectfile "${name}" "${sourcefile}"; local objectfile="${_ret}"
+ objectfiles="${objectfiles} ${objectfile}"
+ done
+ _ret="${objectfiles}"
+}
+
+# get abstract flags in target
+_get_target_abstract_flags() {
+ local name="${1}"
+ local toolkind="${2}"
+ local toolname="${3}"
+ local itemname="${4}"
+ local values="${5}"
+ if test_z "${values}"; then
+
+ # get values from target
+ _get_target_item "${name}" "${itemname}"; values="${_ret}"
+
+ # get values from target deps
+ _get_target_librarydeps "${name}"; local deps="${_ret}"
+ local dep=""
+ for dep in ${deps}; do
+ _get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
+ if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
+ _get_target_item "${dep}" "${itemname}_public"; local depvalues="${_ret}"
+ if test_nz "${depvalues}"; then
+ values="${values} ${depvalues}"
+ fi
+ fi
+ done
+ fi
+ _get_abstract_flags "${toolkind}" "${toolname}" "${itemname}" "${values}"
+}
+
+# get toolchain flags for ar in target
+_get_target_toolchain_flags_for_ar() {
+ _ret="-cr"
+}
+
+# get toolchain flags for gcc in target
+_get_target_toolchain_flags_for_gcc() {
+ local name="${1}"
+ local toolkind="${2}"
+ local flags=""
+ if is_arch "i386"; then
+ flags="-m32"
+ fi
+ _get_target_item "${name}" "kind"; local targetkind="${_ret}"
+ if test_eq "${targetkind}" "shared" && test_eq "${toolkind}" "sh"; then
+ flags="-shared -fPIC"
+ fi
+ _ret="${flags}"
+}
+
+# get toolchain flags for clang in target
+_get_target_toolchain_flags_for_clang() {
+ local name="${1}"
+ local toolkind="${2}"
+ local flags="-Qunused-arguments"
+ if is_arch "i386"; then
+ flags="-m32"
+ fi
+ _get_target_item "${name}" "kind"; local targetkind="${_ret}"
+ if test_eq "${targetkind}" "shared" && test_eq "${toolkind}" "sh"; then
+ flags="-shared -fPIC"
+ fi
+ _ret="${flags}"
+}
+
+# get toolchain flags in target
+_get_target_toolchain_flags() {
+ local name="${1}"
+ local toolkind="${2}"
+ local toolname="${3}"
+ local flags=""
+ case "${toolname}" in
+ gcc) _get_target_toolchain_flags_for_gcc "${name}" "${toolkind}"; flags="${_ret}";;
+ gxx) _get_target_toolchain_flags_for_gcc "${name}" "${toolkind}"; flags="${_ret}";;
+ clang) _get_target_toolchain_flags_for_clang "${name}" "${toolkind}"; flags="${_ret}";;
+ clangxx) _get_target_toolchain_flags_for_clang "${name}" "${toolkind}"; flags="${_ret}";;
+ ar) _get_target_toolchain_flags_for_ar "${name}" "${toolkind}"; flags="${_ret}";;
+ *) raise "unknown toolname(${toolname})!" ;;
+ esac
+ _ret="${flags}"
+}
+
+# get compiler flags in target
+_get_target_compiler_flags() {
+ local name="${1}"
+ local toolkind="${2}"
+ _get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ local result=""
+
+ # get toolchain flags
+ _get_target_toolchain_flags "${name}" "${toolkind}" "${toolname}"; local toolchain_flags="${_ret}"
+ if test_nz "${toolchain_flags}"; then
+ result="${result} ${toolchain_flags}"
+ fi
+
+ # get abstract flags
+ local itemnames="symbols optimizes warnings languages defines undefines includedirs frameworkdirs frameworks"
+ local itemname=""
+ for itemname in ${itemnames}; do
+ _get_target_abstract_flags "${name}" "${toolkind}" "${toolname}" "${itemname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ result="${result} ${flags}"
+ fi
+ done
+
+ # get raw flags, e.g. add_cflags, add_cxxflags
+ _get_flagname "${toolkind}"; local flagname="${_ret}"
+ _get_target_item "${name}" "${flagname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ result="${result} ${flags}"
+ fi
+ if test_eq "${flagname}" "cflags" || test_eq "${flagname}" "cxxflags"; then
+ _get_target_item "${name}" "cxflags"; flags="${_ret}"
+ if test_nz "${flags}"; then
+ result="${result} ${flags}"
+ fi
+ elif test_eq "${flagname}" "mflags" || test_eq "${flagname}" "mxxflags"; then
+ _get_target_item "${name}" "mxflags"; flags="${_ret}"
+ if test_nz "${flags}"; then
+ result="${result} ${flags}"
+ fi
+ fi
+ _ret="${result}"
+}
+
+# get linker flags in target
+_get_target_linker_flags() {
+ local name="${1}"
+ local toolkind="${2}"
+ _get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ local result=""
+
+ # get toolchain flags
+ _get_target_toolchain_flags "${name}" "${toolkind}" "${toolname}"; local toolchain_flags="${_ret}"
+ if test_nz "${toolchain_flags}"; then
+ result="${result} ${toolchain_flags}"
+ fi
+
+ # get flags from target deps
+ _get_target_librarydeps "${name}"; local deps="${_ret}"
+ local dep=""
+ for dep in ${deps}; do
+ _get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
+ if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
+ _get_targetdir "${dep}"; local dep_targetdir="${_ret}"
+ _get_target_basename "${dep}"; local dep_basename="${_ret}"
+ _get_target_abstract_flags "${dep}" "${toolkind}" "${toolname}" "linkdirs" "${dep_targetdir}"; local linkdirs_flags="${_ret}"
+ _get_target_abstract_flags "${dep}" "${toolkind}" "${toolname}" "links" "${dep_basename}"; local links_flags="${_ret}"
+ if test_eq "${dep_kind}" "shared"; then
+ local rpathdir="@loader_path"
+ _get_targetdir "${name}"; local targetdir="${_ret}"
+ path_relative "${targetdir}" "${dep_targetdir}"; local subdir="${_ret}"
+ if test_nz "${subdir}"; then
+ rpathdir="${rpathdir}/${subdir}"
+ fi
+ _get_target_abstract_flags "${dep}" "${toolkind}" "${toolname}" "rpathdirs" "${rpathdir}"; local rpathdirs_flags="${_ret}"
+ result="${result} ${rpathdirs_flags}"
+ fi
+ result="${result} ${linkdirs_flags} ${links_flags}"
+ fi
+ done
+
+ # get abstract flags
+ local itemnames="strip frameworkdirs linkdirs links rpathdirs frameworks syslinks"
+ local itemname=""
+ for itemname in ${itemnames}; do
+ _get_target_abstract_flags "${name}" "${toolkind}" "${toolname}" "${itemname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ result="${result} ${flags}"
+ fi
+ done
+
+ # get raw flags, e.g. add_ldflags, add_shflags
+ _get_flagname "${toolkind}"; local flagname="${_ret}"
+ _get_target_item "${name}" "${flagname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ result="${result} ${flags}"
+ fi
+
+ _ret="${result}"
+}
+
+# get archiver flags in target
+_get_target_archiver_flags() {
+ local name="${1}"
+ local toolkind="${2}"
+ _get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ local result=""
+
+ # get toolchain flags
+ _get_target_toolchain_flags "${name}" "${toolkind}" "${toolname}"; local toolchain_flags="${_ret}"
+ if test_nz "${toolchain_flags}"; then
+ result="${result} ${toolchain_flags}"
+ fi
+
+ # get raw flags, e.g. add_arflags
+ _get_flagname "${toolkind}"; local flagname="${_ret}"
+ _get_target_item "${name}" "${flagname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ result="${result} ${flags}"
+ fi
+
+ _ret="${result}"
+}
+
+# get target flags
+_get_target_flags() {
+ local name="${1}"
+ local toolkind="${2}"
+ local flags=""
+ if test_eq "${toolkind}" "sh"; then
+ _get_target_linker_flags "${name}" "${toolkind}"; flags="${_ret}"
+ elif test_eq "${toolkind}" "ld"; then
+ _get_target_linker_flags "${name}" "${toolkind}"; flags="${_ret}"
+ elif test_eq "${toolkind}" "ar"; then
+ _get_target_archiver_flags "${name}" "${toolkind}"; flags="${_ret}"
+ else
+ _get_target_compiler_flags "${name}" "${toolkind}"; flags="${_ret}"
+ fi
+ _ret="${flags}"
+}
+
+# add file paths in target
+_add_target_filepaths() {
+ local key="$1"
+ shift
+ # we need avoid escape `*` automatically in for-loop
+ local file=""
+ string_replace "${@}" "\*" "?"; local list="${_ret}"
+ if test_eq "${key}" "files"; then
+ for file in ${list}; do
+ path_sourcekind "${file}"; local sourcekind="${_ret}"
+ _targets_toolkinds="${_targets_toolkinds} ${sourcekind}"
+ done
+ fi
+ for file in ${list}; do
+ string_replace "${file}" "?" "*"; file="${_ret}"
+ if ! path_is_absolute "${file}"; then
+ file="${xmake_sh_scriptdir}/${file}"
+ fi
+ local files=""
+ if string_contains_star2 "${file}"; then
+ path_directory "${file}"; local dir="${_ret}"
+ path_filename_fromdir "${file}" "${dir}"; local name="${_ret}"
+ _os_find "${dir}" "${name}"; files="${_ret}"
+ elif string_contains_star "${file}"; then
+ path_directory "${file}"; local dir="${_ret}"
+ path_filename_fromdir "${file}" "${dir}"; local name="${_ret}"
+ _os_find "${dir}" "${name}" 1; files="${_ret}"
+ else
+ files="${file}"
+ fi
+ for file in ${files}; do
+ path_relative "${xmake_sh_projectdir}" "${file}"; file="${_ret}"
+ _add_target_item "${_xmake_sh_target_current}" "${key}" "${file}"
+ done
+ done
+}
+
+# add install paths in target
+_add_target_installpaths() {
+ local key="$1"
+ local filepattern="${2}"
+ local prefixdir="${3}"
+
+ # get root directory, e.g. "src/foo/(*.h)" -> "src/foo"
+ local rootdir=""
+ if string_contains "${filepattern}" "("; then
+ string_split "${filepattern}" "(" 1; rootdir="${_ret}"
+ rootdir=${rootdir%/}
+ if ! path_is_absolute "${rootdir}"; then
+ rootdir="${xmake_sh_scriptdir}/${rootdir}"
+ fi
+ path_relative "${xmake_sh_projectdir}" "${rootdir}"; rootdir="${_ret}"
+ rootdir=${rootdir%/}
+ fi
+
+ # remove (), e.g. "src/(*.h)" -> "src/*.h"
+ string_replace ${filepattern} "(" ""; filepattern="${_ret}"
+ string_replace ${filepattern} ")" ""; filepattern="${_ret}"
+
+ # get real path
+ if ! path_is_absolute "${filepattern}"; then
+ filepattern="${xmake_sh_scriptdir}/${filepattern}"
+ fi
+ local files=""
+ if string_contains_star2 "${filepattern}"; then
+ path_directory "${filepattern}"; local dir="${_ret}"
+ path_filename_fromdir "${filepattern}" "${dir}"; local name="${_ret}"
+ _os_find "${dir}" "${name}"; files="${_ret}"
+ elif string_contains_star "${filepattern}"; then
+ path_directory "${filepattern}"; local dir="${_ret}"
+ path_filename_fromdir "${filepattern}" "${dir}"; local name="${_ret}"
+ _os_find "${dir}" "${name}" 1; files="${_ret}"
+ else
+ files="${filepattern}"
+ fi
+ for file in ${files}; do
+ path_relative "${xmake_sh_projectdir}" "${file}"; file="${_ret}"
+ _add_target_item "${_xmake_sh_target_current}" "${key}" "${file}:${rootdir}:${prefixdir}"
+ done
+}
+
+# set target file path
+_set_target_filepath() {
+ local key="${1}"
+ local path="${2}"
+ if ! path_is_absolute "${path}"; then
+ path="${xmake_sh_scriptdir}/${path}"
+ fi
+ path_relative ${xmake_sh_projectdir} "${path}"; path="${_ret}"
+ _set_target_item "${_xmake_sh_target_current}" "${key}" "${path}"
+}
+
+# set kind in target
+set_kind() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local kind=${1}
+ _set_target_item "${_xmake_sh_target_current}" "kind" "${kind}"
+ case "${kind}" in
+ binary) _targets_toolkinds="${_targets_toolkinds} ld";;
+ static) _targets_toolkinds="${_targets_toolkinds} ar";;
+ shared) _targets_toolkinds="${_targets_toolkinds} sh";;
+ *) raise "unknown target kind ${kind}";;
+ esac
+}
+
+# set version in target
+set_version() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local version="${1}"
+ local version_build="${2}"
+ _set_target_item "${_xmake_sh_target_current}" "version" "${version}"
+ _set_target_item "${_xmake_sh_target_current}" "version_build" "${version_build}"
+}
+
+# set default in target
+set_default() {
+ local default=${1}
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _set_target_item "${_xmake_sh_target_current}" "default" "${default}"
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ _set_option_item "${_xmake_sh_option_current}" "default" "${default}"
+ fi
+}
+
+# set configvar in target
+set_configvar() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local name="${1}"
+ local value="${2}"
+ _set_target_item "${_xmake_sh_target_current}" "configvar_${name}" "${value}"
+ _add_target_item "${_xmake_sh_target_current}" "configvars" "${name}"
+}
+
+# set filename in target
+set_filename() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local filename="${1}"
+ _set_target_item "${_xmake_sh_target_current}" "filename" "${filename}"
+}
+
+# set basename in target
+set_basename() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local basename="${1}"
+ _set_target_item "${_xmake_sh_target_current}" "basename" "${basename}"
+}
+
+# set extension in target
+set_extension() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local extension=${1}
+ _set_target_item "${_xmake_sh_target_current}" "extension" "${extension}"
+}
+
+# set prefixname in target
+set_prefixname() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local prefixname=${1}
+ _set_target_item "${_xmake_sh_target_current}" "prefixname" "${prefixname}"
+}
+
+# set target directory
+set_targetdir() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _set_target_filepath "targetdir" "${1}"
+}
+
+# set target object directory
+set_objectdir() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _set_target_filepath "objectdir" "${1}"
+}
+
+# set target config directory
+set_configdir() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _set_target_filepath "configdir" "${1}"
+}
+
+# set target install directory
+set_installdir() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _set_target_filepath "installdir" "${1}"
+}
+
+# add deps in target
+add_deps() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local dep=""
+ for dep in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "deps" "${dep}"
+ done
+}
+
+# add files in target
+add_files() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _add_target_filepaths "files" "$@"
+}
+
+# add install files in target
+add_installfiles() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _add_target_installpaths "installfiles" "$@"
+}
+
+# add header files in target
+add_headerfiles() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _add_target_installpaths "headerfiles" "$@"
+}
+
+# add config files in target
+add_configfiles() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ _add_target_filepaths "configfiles" "$@"
+}
+
+# add defines in target
+add_defines() {
+ local define=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ local public=false
+ for define in $@; do
+ if test_nq "${define}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "defines" "${define}"
+ else
+ public=true
+ fi
+ done
+ if ${public}; then
+ for define in $@; do
+ if test_nq "${define}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "defines_public" "${define}"
+ fi
+ done
+ fi
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for define in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "defines" "${define}"
+ done
+ fi
+}
+
+# add udefines in target
+add_udefines() {
+ local undefine=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ local public=false
+ for undefine in $@; do
+ if test_nq "${undefine}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "undefines" "${undefine}"
+ else
+ public=true
+ fi
+ done
+ if ${public}; then
+ for undefine in $@; do
+ if test_nq "${undefine}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "undefines_public" "${undefine}"
+ fi
+ done
+ fi
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for udefine in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "udefines" "${udefine}"
+ done
+ fi
+}
+
+# add includedirs in target
+add_includedirs() {
+ local public=false
+ local dir=""
+ for dir in $@; do
+ if test_nq "${dir}" "{public}"; then
+ if ! path_is_absolute "${dir}"; then
+ dir="${xmake_sh_scriptdir}/${dir}"
+ fi
+ path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _add_target_item "${_xmake_sh_target_current}" "includedirs" "${dir}"
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ _add_option_item "${_xmake_sh_option_current}" "includedirs" "${dir}"
+ fi
+ else
+ public=true
+ fi
+ done
+ if ${public}; then
+ for dir in $@; do
+ if test_nq "${dir}" "{public}"; then
+ if ! path_is_absolute "${dir}"; then
+ dir="${xmake_sh_scriptdir}/${dir}"
+ fi
+ path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _add_target_item "${_xmake_sh_target_current}" "includedirs_public" "${dir}"
+ fi
+ fi
+ done
+ fi
+}
+
+# add links in target
+add_links() {
+ local link=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ local public=false
+ for link in $@; do
+ if test_nq "${link}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "links" "${link}"
+ else
+ public=true
+ fi
+ done
+ if ${public}; then
+ for link in $@; do
+ if test_nq "${link}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "links_public" "${link}"
+ fi
+ done
+ fi
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for link in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "links" "${link}"
+ done
+ fi
+}
+
+# add syslinks in target
+add_syslinks() {
+ local syslink=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ local public=false
+ for syslink in $@; do
+ if test_nq "${syslink}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "syslinks" "${syslink}"
+ else
+ public=true
+ fi
+ done
+ if ${public}; then
+ for syslink in $@; do
+ if test_nq "${syslink}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "syslinks_public" "${syslink}"
+ fi
+ done
+ fi
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for syslink in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "syslinks" "${syslink}"
+ done
+ fi
+}
+
+# add linkdirs in target
+add_linkdirs() {
+ local dir=""
+ local public=false
+ for dir in $@; do
+ if test_nq "${dir}" "{public}"; then
+ if ! path_is_absolute "${dir}"; then
+ dir="${xmake_sh_scriptdir}/${dir}"
+ fi
+ path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _add_target_item "${_xmake_sh_target_current}" "linkdirs" "${dir}"
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ _add_option_item "${_xmake_sh_option_current}" "linkdirs" "${dir}"
+ fi
+ else
+ public=true
+ fi
+ done
+ if ${public}; then
+ for dir in $@; do
+ if test_nq "${dir}" "{public}"; then
+ if ! path_is_absolute "${dir}"; then
+ dir="${xmake_sh_scriptdir}/${dir}"
+ fi
+ path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _add_target_item "${_xmake_sh_target_current}" "linkdirs_public" "${dir}"
+ fi
+ fi
+ done
+ fi
+}
+
+# add rpathdirs in target
+add_rpathdirs() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local dir=""
+ for dir in $@; do
+ if ! path_is_absolute "${dir}"; then
+ dir="${xmake_sh_scriptdir}/${dir}"
+ fi
+ path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
+ _add_target_item "${_xmake_sh_target_current}" "rpathdirs" "${dir}"
+ done
+}
+
+# add frameworks in target
+add_frameworks() {
+ local framework=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ local public=false
+ for framework in $@; do
+ if test_nq "${framework}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "frameworks" "${framework}"
+ else
+ public=true
+ fi
+ done
+ if ${public}; then
+ for framework in $@; do
+ if test_nq "${framework}" "{public}"; then
+ _add_target_item "${_xmake_sh_target_current}" "frameworks_public" "${framework}"
+ fi
+ done
+ fi
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for framework in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "frameworks" "${framework}"
+ done
+ fi
+}
+
+# add frameworkdirs in target
+add_frameworkdirs() {
+ local dir=""
+ for dir in $@; do
+ if ! path_is_absolute "${dir}"; then
+ dir="${xmake_sh_scriptdir}/${dir}"
+ fi
+ path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _add_target_item "${_xmake_sh_target_current}" "frameworkdirs" "${dir}"
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ _add_option_item "${_xmake_sh_option_current}" "frameworkdirs" "${dir}"
+ fi
+ done
+}
+
+# set strip in target
+set_strip() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local strip=${1}
+ _set_target_item "${_xmake_sh_target_current}" "strip" "${strip}"
+}
+
+# set symbols in target
+set_symbols() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local symbols="${1}"
+ _set_target_item "${_xmake_sh_target_current}" "symbols" "${symbols}"
+}
+
+# set languages in target
+set_languages() {
+ local languages="${@}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _set_target_item "${_xmake_sh_target_current}" "languages" "${languages}"
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ _set_option_item "${_xmake_sh_option_current}" "languages" "${languages}"
+ fi
+}
+
+# set warnings in target
+set_warnings() {
+ local warnings="${@}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _set_target_item "${_xmake_sh_target_current}" "warnings" "${warnings}"
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ _set_option_item "${_xmake_sh_option_current}" "warnings" "${warnings}"
+ fi
+}
+
+# set optimizes in target
+set_optimizes() {
+ local optimizes="${@}"
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ _set_target_item "${_xmake_sh_target_current}" "optimizes" "${optimizes}"
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ _set_option_item "${_xmake_sh_option_current}" "optimizes" "${optimizes}"
+ fi
+}
+
+# add cflags in target
+add_cflags() {
+ local flag=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "cflags" "${flag}"
+ done
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for flag in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "cflags" "${flag}"
+ done
+ fi
+}
+
+# add cxflags in target
+add_cxflags() {
+ local flag=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "cxflags" "${flag}"
+ done
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for flag in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "cxflags" "${flag}"
+ done
+ fi
+}
+
+# add cxxflags in target
+add_cxxflags() {
+ local flag=""
+ if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "cxxflags" "${flag}"
+ done
+ elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
+ for flag in $@; do
+ _add_option_item "${_xmake_sh_option_current}" "cxxflags" "${flag}"
+ done
+ fi
+}
+
+# add asflags in target
+add_asflags() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local flag=""
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "asflags" "${flag}"
+ done
+}
+
+# add mflags in target
+add_mflags() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local flag=""
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "mflags" "${flag}"
+ done
+}
+
+# add mxflags in target
+add_mxflags() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local flag=""
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "mxflags" "${flag}"
+ done
+}
+
+# add mxxflags in target
+add_mxxflags() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local flag=""
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "mxxflags" "${flag}"
+ done
+}
+
+# add ldflags in target
+add_ldflags() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local flag=""
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "ldflags" "${flag}"
+ done
+}
+
+# add shflags in target
+add_shflags() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local flag=""
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "shflags" "${flag}"
+ done
+}
+
+# add arflags in target
+add_arflags() {
+ if ! ${_loading_targets}; then
+ return
+ fi
+ local flag=""
+ for flag in $@; do
+ _add_target_item "${_xmake_sh_target_current}" "arflags" "${flag}"
+ done
+}
+
+#-----------------------------------------------------------------------------
+# toolchain configuration apis
+#
+
+# define toolchain
+toolchain() {
+ local name="${1}"
+ _xmake_sh_toolchain_current="${name}"
+ if ! ${_loading_toolchains}; then
+ return
+ fi
+ _xmake_sh_toolchains="${_xmake_sh_toolchains} ${name}"
+ _map_set "toolchains" "${name}_name" "${name}"
+ return 0
+}
+toolchain_end() {
+ _xmake_sh_toolchain_current=""
+}
+_map "toolchains"
+
+# has the given toolchain?
+_has_toolchain() {
+ local name=${1}
+ if _map_has "toolchains" "${name}_name"; then
+ return 0
+ fi
+ return 1
+}
+
+# get the given toolchain item
+_get_toolchain_item() {
+ local name=${1}
+ local key=${2}
+ _map_get "toolchains" "${name}_${key}"
+}
+
+# set the given toolchain item
+_set_toolchain_item() {
+ local name=${1}
+ local key=${2}
+ local value=${3}
+ if test_nz "${name}"; then
+ _map_set "toolchains" "${name}_${key}" "${value}"
+ else
+ raise "please set toolchain in the toolchain scope!"
+ fi
+}
+
+# get the give toolchain toolset
+_get_toolchain_toolset() {
+ local name=${1}
+ local kind=${2}
+ _get_toolchain_item "${name}" "toolset_${kind}"
+}
+
+# set the give toolchain toolset
+_set_toolchain_toolset() {
+ local name=${1}
+ local kind=${2}
+ local programs="${3}"
+ _set_toolchain_item "${name}" "toolset_${kind}" "${programs}"
+}
+
+# add the give toolchain toolset
+_add_toolchain_toolset() {
+ local name=${1}
+ local kind=${2}
+ local program="${3}"
+ _get_toolchain_item "${name}" "toolset_${kind}"; local programs="${_ret}"
+ if test_nz "${programs}"; then
+ programs="${programs}:${program}"
+ else
+ programs="${program}"
+ fi
+ _set_toolchain_item "${name}" "toolset_${kind}" "${programs}"
+}
+
+# set toolset in toolchain
+set_toolset() {
+ if ! ${_loading_toolchains}; then
+ return
+ fi
+ local kind=${1}
+ shift
+ local idx=0
+ while test $# != 0; do
+ local program="${1}"
+ local key="${kind}"
+ if test_nq "${idx}" "0"; then
+ key="${key}_${idx}"
+ fi
+ _set_toolchain_toolset "${_xmake_sh_toolchain_current}" "${key}" "${program}"
+ idx=$((idx+1))
+ shift
+ done
+}
+
+#-----------------------------------------------------------------------------
+# load options
+#
+
+# load options and toolchains
+_load_options_and_toolchains() {
+ _loading_options=true
+ _loading_toolchains=true
+ _loading_targets=false
+ local file=${xmake_sh_projectdir}/xmake.sh
+ if test -f "${file}"; then
+ includes "${file}"
+ else
+ # include all xmake.sh files in next sub-directories
+ local files=`find ${xmake_sh_projectdir} -maxdepth 2 -mindepth 2 -name "xmake.sh"`
+ for file in ${files}; do
+ includes "${file}"
+ done
+ fi
+}
+_load_options_and_toolchains
+
+# show option usage
+_show_options_usage() {
+ _get_options_for_menu; local options="${_ret}"
+ for name in ${options}; do
+ _get_option_item "${name}" "description"; local description="${_ret}"
+ _get_option_item "${name}" "default"; local default="${_ret}"
+ string_toupper ${name}; local head="--${name}="${_ret}""
+ local headsize=${#head}
+ local tail="${description}"
+ if test "x${default}" != "x"; then
+ local defval=${default}
+ if test "x${defval}" = "xtrue"; then
+ defval="yes"
+ elif test "x${defval}" = "xfalse"; then
+ defval="no"
+ fi
+ tail="${tail} (default: ${defval})"
+ fi
+ local width=24
+ local padding_width=$((${width} - ${headsize}))
+ local padding=$(string_dupch ${padding_width} " ")
+ echo " ${head}${padding}${tail}"
+ done
+}
+
+# show configure usage
+_show_usage() {
+echo '
+Usage: '"$0"' [<options>...]
+Options: [defaults in brackets after descriptions]
+Common options:
+ --help Print this message.
+ --version Only print version information.
+ --verbose Display more information.
+ --diagnosis Display lots of diagnosis information.
+
+ --generator=GENERATOR Set the project generator. (default: '"${_project_generator}"')
+ - gmake
+ - ninja
+ --make=MAKE Set the make program. (default: '"${_make_program_default}"')
+ --ninja=NINJA Set the Ninja program. (default: '"${_ninja_program_default}"')
+ --plat=PLAT Compile for the given platform. (default: '"${_target_plat_default}"')
+ - msys
+ - cross
+ - bsd
+ - mingw
+ - macosx
+ - linux
+ --arch=ARCH Compile for the given architecture. (default: '"${_target_arch_default}"')
+ - msys: i386 x86_64
+ - cross: i386 x86_64 arm arm64 mips mips64 riscv riscv64 s390x ppc ppc64 sh4
+ - bsd: i386 x86_64
+ - mingw: i386 x86_64 arm arm64
+ - macosx: x86_64 arm64
+ - linux: i386 x86_64 armv7 armv7s arm64-v8a mips mips64 mipsel mips64el
+ --mode=MODE Set the given compilation mode. (default: '"${_target_mode_default}"')
+ - release
+ - debug
+ --toolchain=TOOLCHAIN Set toolchain name.
+ - clang
+ - gcc
+
+ --prefix=PREFIX Set install files directory in tree rooted at PREFIX. (default: '"${_install_prefix_default}"')
+ --bindir=DIR Set install binaries directory in PREFIX/DIR. (default: '"${_install_bindir_default}"')
+ --libdir=DIR Set install libraries directory in PREFIX/DIR. (default: '"${_install_libdir_default}"')
+ --includedir=DIR Set install includes directory in PREFIX/DIR. (default: '"${_install_includedir_default}"')
+ --buildir=DIR Set build directory. (default: '"${xmake_sh_buildir}"')
+
+Project options:
+'"$(_show_options_usage)"'
+'
+ exit 1
+}
+
+# show xmake.sh version
+_show_version() {
+ echo "xmake.sh v${xmake_sh_version}, A script-only build utility like autotools"
+ echo "${xmake_sh_copyright}"
+ echo ' _ _ '
+ echo " __ ___ __ __ __ _| | ______ ___| |__ "
+ echo " \ \/ / | \/ |/ _ | |/ / __ \ / __| '_ \ "
+ echo " > < | \__/ | /_| | < ___/_\__ \ | | | "
+ echo " /_/\_\_|_| |_|\__ \|_|\_\____(_)___/_| |_| "
+ echo ' by ruki, xmake.io'
+ echo ' '
+ echo ' 👉 Manual: https://xmake.io/#/getting_started '
+ echo ' 🙏 Donate: https://xmake.io/#/sponsor '
+ echo ' '
+ exit 2
+}
+
+# --foo=yes => foo
+_parse_argument_name() {
+ _ret=$(echo "${1#*--}" | sed "s/${2-=[^=]*}$//")
+}
+
+# --foo=yes => yes
+_parse_argument_value() {
+ _ret=$(echo "$1" | sed "s/^${2-[^=]*=}//")
+}
+
+# parse input arguments
+_handle_option() {
+ _parse_argument_name ${1}; local name="${_ret}"
+ _parse_argument_value ${1}; local value="${_ret}"
+ if test_eq "${name}" "help"; then
+ _show_usage
+ return 0
+ elif test_eq "${name}" "version"; then
+ _show_version
+ return 0
+ elif test_eq "${name}" "verbose"; then
+ xmake_sh_verbose=true
+ return 0
+ elif test_eq "${name}" "diagnosis"; then
+ xmake_sh_diagnosis=true
+ return 0
+ elif test_eq "${name}" "plat"; then
+ _target_plat=${value}
+ return 0
+ elif test_eq "${name}" "arch"; then
+ _target_arch=${value}
+ return 0
+ elif test_eq "${name}" "mode"; then
+ _target_mode=${value}
+ return 0
+ elif test_eq "${name}" "toolchain"; then
+ _target_toolchain=${value}
+ return 0
+ elif test_eq "${name}" "generator"; then
+ _project_generator=${value}
+ return 0
+ elif test_eq "${name}" "make"; then
+ _make_program=${value}
+ return 0
+ elif test_eq "${name}" "ninja"; then
+ _ninja_program=${value}
+ return 0
+ elif test_eq "${name}" "prefix"; then
+ _install_prefix_default="${value}"
+ return 0
+ elif test_eq "${name}" "bindir"; then
+ _install_bindir_default="${value}"
+ return 0
+ elif test_eq "${name}" "libdir"; then
+ _install_libdir_default="${value}"
+ return 0
+ elif test_eq "${name}" "includedir"; then
+ _install_includedir_default="${value}"
+ return 0
+ elif test_eq "${name}" "buildir"; then
+ xmake_sh_buildir="${value}"
+ return 0
+ elif _has_option "${name}"; then
+ _set_option_value "${name}" "${value}"
+ return 0
+ fi
+ return 1
+}
+while test $# != 0; do
+ if _handle_option ${1}; then
+ shift
+ else
+ raise "Unknown option: $1"
+ fi
+done
+
+#-----------------------------------------------------------------------------
+# detect platform and toolchains
+#
+
+# envs toolchain
+toolchain "envs"
+ set_toolset "as" "$CC" "$CXX" "$AS"
+ set_toolset "cc" "$CC"
+ set_toolset "cxx" "$CC" "$CXX"
+ set_toolset "mm" "$CC" "$CXX"
+ set_toolset "mxx" "$CC" "$CXX"
+ set_toolset "ld" "$CXX" "$CC" "$LD"
+ set_toolset "sh" "$CXX" "$CC" "$LD"
+ set_toolset "ar" "$AR"
+toolchain_end
+
+# clang toolchain
+toolchain "clang"
+ set_toolset "as" "clang"
+ set_toolset "cc" "clang"
+ set_toolset "cxx" "clang" "clang++"
+ set_toolset "mm" "clang"
+ set_toolset "mxx" "clang" "clang++"
+ set_toolset "ld" "clang++" "clang"
+ set_toolset "sh" "clang++" "clang"
+ set_toolset "ar" "ar"
+toolchain_end
+
+# gcc toolchain
+toolchain "gcc"
+ set_toolset "as" "gcc"
+ set_toolset "cc" "gcc"
+ set_toolset "cxx" "gcc" "g++"
+ set_toolset "mm" "gcc"
+ set_toolset "mxx" "gcc" "g++"
+ set_toolset "ld" "g++" "gcc"
+ set_toolset "sh" "g++" "gcc"
+ set_toolset "ar" "ar"
+toolchain_end
+
+# mingw toolchain (x86_64)
+toolchain "x86_64_w64_mingw32"
+ set_toolset "as" "x86_64-w64-mingw32-gcc"
+ set_toolset "cc" "x86_64-w64-mingw32-gcc"
+ set_toolset "cxx" "x86_64-w64-mingw32-gcc" "x86_64-w64-mingw32-g++"
+ set_toolset "mm" "x86_64-w64-mingw32-gcc"
+ set_toolset "mxx" "x86_64-w64-mingw32-gcc" "x86_64-w64-mingw32-g++"
+ set_toolset "ld" "x86_64-w64-mingw32-g++" "x86_64-w64-mingw32-gcc"
+ set_toolset "sh" "x86_64-w64-mingw32-g++" "x86_64-w64-mingw32-gcc"
+ set_toolset "ar" "x86_64-w64-mingw32-ar" "ar"
+toolchain_end
+
+# mingw toolchain (i686)
+toolchain "i686_w64_mingw32"
+ set_toolset "as" "i686-w64-mingw32-gcc"
+ set_toolset "cc" "i686-w64-mingw32-gcc"
+ set_toolset "cxx" "i686-w64-mingw32-gcc" "i686-w64-mingw32-g++"
+ set_toolset "mm" "i686-w64-mingw32-gcc"
+ set_toolset "mxx" "i686-w64-mingw32-gcc" "i686-w64-mingw32-g++"
+ set_toolset "ld" "i686-w64-mingw32-g++" "i686-w64-mingw32-gcc"
+ set_toolset "sh" "i686-w64-mingw32-g++" "i686-w64-mingw32-gcc"
+ set_toolset "ar" "i686-w64-mingw32-ar" "ar"
+toolchain_end
+
+# check platform
+_check_platform() {
+ if test "x${_target_plat}" = "x"; then
+ _target_plat=${_target_plat_default}
+ fi
+ if test "x${_target_arch}" = "x"; then
+ _target_arch=${_target_arch_default}
+ fi
+ if test "x${_target_mode}" = "x"; then
+ _target_mode=${_target_mode_default}
+ fi
+ echo "checking for platform ... ${_target_plat}"
+ echo "checking for architecture ... ${_target_arch}"
+}
+
+# get toolchain compile command for gcc/clang
+_toolchain_compcmd_for_gcc_clang() {
+ local program="${1}"
+ local objectfile="${2}"
+ local sourcefile="${3}"
+ local flags="${4}"
+ _ret="${program} -c ${flags} -o ${objectfile} ${sourcefile}"
+}
+
+# get toolchain link command for gcc/clang
+_toolchain_linkcmd_for_gcc_clang() {
+ local toolkind="${1}"
+ local program="${2}"
+ local binaryfile="${3}"
+ local objectfiles="${4}"
+ local flags="${5}"
+ if test_eq "${toolkind}" "sh"; then
+ flags="-shared -fPIC ${flags}"
+ fi
+ _ret="${program} -o ${binaryfile} ${objectfiles} ${flags}"
+}
+
+# get toolchain link command for ar
+_toolchain_linkcmd_for_ar() {
+ local toolkind="${1}"
+ local program="${2}"
+ local binaryfile="${3}"
+ local objectfiles="${4}"
+ local flags="${5}"
+ _ret="${program} ${flags} ${binaryfile} ${objectfiles}"
+}
+
+# get toolchain compile command
+_toolchain_compcmd() {
+ local sourcekind="${1}"
+ local objectfile="${2}"
+ local sourcefile="${3}"
+ local flags="${4}"
+ _get_toolchain_toolset "${_target_toolchain}" "${sourcekind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ local compcmd=""
+ case "${toolname}" in
+ gcc) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
+ gxx) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
+ clang) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
+ clangxx) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
+ *) raise "unknown toolname(${toolname})!" ;;
+ esac
+ _ret="${compcmd}"
+}
+
+# get toolchain link command
+_toolchain_linkcmd() {
+ local toolkind="${1}"
+ local binaryfile="${2}"
+ local objectfiles="${3}"
+ local flags="${4}"
+ _get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ case "${toolname}" in
+ gcc) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
+ gxx) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
+ clang) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
+ clangxx) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
+ ar) _toolchain_linkcmd_for_ar "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
+ *) raise "unknown toolname(${toolname})!" ;;
+ esac
+ _ret="${linkcmd}"
+}
+
+# try make
+_toolchain_try_make() {
+ local program=${1}
+ if _os_runv "${program}" "--version"; then
+ return 0
+ fi
+ return 1
+}
+
+# try ninja
+_toolchain_try_ninja() {
+ local program=${1}
+ if _os_runv "${program}" "--version"; then
+ return 0
+ fi
+ return 1
+}
+
+# try gcc
+_toolchain_try_gcc() {
+ if test "x${_toolchain_try_gcc_result}" = "xok"; then
+ return 0
+ elif test "x${_toolchain_try_gcc_result}" = "xno"; then
+ return 1
+ fi
+
+ local kind=${1}
+ local program=${2}
+ if _os_runv "${program}" "--version"; then
+ _toolchain_try_gcc_result="ok"
+ return 0
+ fi
+ _toolchain_try_gcc_result="no"
+ return 1
+}
+
+# try g++
+_toolchain_try_gxx() {
+ if test "x${_toolchain_try_gxx_result}" = "xok"; then
+ return 0
+ elif test "x${_toolchain_try_gxx_result}" = "xno"; then
+ return 1
+ fi
+
+ local kind=${1}
+ local program=${2}
+ if _os_runv "${program}" "--version"; then
+ _toolchain_try_gxx_result="ok"
+ return 0
+ fi
+ _toolchain_try_gxx_result="no"
+ return 1
+}
+
+# try clang
+_toolchain_try_clang() {
+ if test "x${_toolchain_try_clang_result}" = "xok"; then
+ return 0
+ elif test "x${_toolchain_try_clang_result}" = "xno"; then
+ return 1
+ fi
+
+ local kind=${1}
+ local program=${2}
+ if _os_runv "${program}" "--version"; then
+ _toolchain_try_clang_result="ok"
+ return 0
+ fi
+ _toolchain_try_clang_result="no"
+ return 1
+}
+
+# try clang++
+_toolchain_try_clangxx() {
+ if test "x${_toolchain_try_clangxx_result}" = "xok"; then
+ return 0
+ elif test "x${_toolchain_try_clangxx_result}" = "xno"; then
+ return 1
+ fi
+
+ local kind=${1}
+ local program=${2}
+ if _os_runv "${program}" "--version"; then
+ _toolchain_try_clangxx_result="ok"
+ return 0
+ fi
+ _toolchain_try_clangxx_result="no"
+ return 1
+}
+
+# TODO try ar
+_toolchain_try_ar() {
+ local kind=${1}
+ local program=${2}
+
+ # generate the source file
+ _os_tmpfile
+ local tmpfile="${_ret}"
+ local objectfile="${tmpfile}.o"
+ local libraryfile="${tmpfile}.a"
+ echo "" > "${objectfile}"
+
+ # try linking it
+ local ok=false
+ if _os_runv "${program}" "-cr" "${libraryfile}" "${objectfile}"; then
+ ok=true
+ fi
+
+ # remove files
+ _os_tryrm "${objectfile}"
+ _os_tryrm "${libraryfile}"
+ if ${ok}; then
+ return 0
+ fi
+ return 1
+}
+
+# try program
+_toolchain_try_program() {
+ local toolchain=${1}
+ local kind=${2}
+ local program=${3}
+ local ok=false
+ path_toolname "${program}"; local toolname="${_ret}"
+ case "${toolname}" in
+ gcc) _toolchain_try_gcc "${kind}" "${program}" && ok=true;;
+ gxx) _toolchain_try_gxx "${kind}" "${program}" && ok=true;;
+ clang) _toolchain_try_clang "${kind}" "${program}" && ok=true;;
+ clangxx) _toolchain_try_clangxx "${kind}" "${program}" && ok=true;;
+ ar) _toolchain_try_ar "${kind}" "${program}" && ok=true;;
+ *) raise "unknown toolname(${toolname})!" ;;
+ esac
+ if ${ok}; then
+ vprint "checking for ${program} ... ok"
+ return 0
+ fi
+ vprint "checking for ${program} ... no"
+ return 1
+}
+
+# try toolset
+_toolchain_try_toolset() {
+ local toolchain=${1}
+ local kind=${2}
+ local description=${3}
+ local indices="0 1 2 3 4 5"
+ for idx in ${indices}; do
+ local key="${kind}"
+ if test_nq "${idx}" "0"; then
+ key="${key}_${idx}"
+ fi
+ _get_toolchain_toolset "${toolchain}" "${key}"; local program="${_ret}"
+ if test_nz "${program}"; then
+ if _toolchain_try_program "${toolchain}" "${kind}" "${program}"; then
+ _set_toolchain_toolset "${toolchain}" "${kind}" "${program}"
+ echo "checking for the ${description} (${kind}) ... ${program}"
+ return 0
+ fi
+ fi
+ done
+ return 1
+}
+
+# try toolchain
+_toolchain_try() {
+ local toolchain=${1}
+ vprint "checking for $toolchain toolchain ..."
+ if _toolchain_try_toolset "${toolchain}" "cc" "c compiler" &&
+ _toolchain_try_toolset "${toolchain}" "cxx" "c++ compiler" &&
+ _toolchain_try_toolset "${toolchain}" "as" "assembler" &&
+ _toolchain_try_toolset "${toolchain}" "mm" "objc compiler" &&
+ _toolchain_try_toolset "${toolchain}" "mxx" "objc++ compiler" &&
+ _toolchain_try_toolset "${toolchain}" "ld" "linker" &&
+ _toolchain_try_toolset "${toolchain}" "ar" "static library archiver" &&
+ _toolchain_try_toolset "${toolchain}" "sh" "shared library linker"; then
+ return 0
+ fi
+ return 1
+}
+
+# detect make
+_toolchain_detect_make() {
+ if test "x${_make_program}" = "x"; then
+ _make_program=${_make_program_default}
+ fi
+ if _toolchain_try_make "${_make_program}"; then
+ echo "checking for make ... ok"
+ else
+ echo "checking for make ... no"
+ raise "make not found!"
+ fi
+}
+
+# detect ninja
+_toolchain_detect_ninja() {
+ if test "x${_ninja_program}" = "x"; then
+ _ninja_program=${_ninja_program_default}
+ fi
+ if _toolchain_try_ninja "${_ninja_program}"; then
+ echo "checking for ninja ... ok"
+ else
+ echo "checking for ninja ... no"
+ raise "ninja not found!"
+ fi
+}
+
+# detect build backend
+_toolchain_detect_backend() {
+ if test "x${_project_generator}" = "xgmake"; then
+ _toolchain_detect_make
+ elif test "x${_project_generator}" = "xninja"; then
+ _toolchain_detect_ninja
+ fi
+}
+
+# detect toolchain
+_toolchain_detect() {
+ # detect build backend
+ _toolchain_detect_backend
+
+ # detect toolchains
+ local toolchains="${1}"
+ if test "x${toolchains}" = "x"; then
+ if is_plat "macosx"; then
+ toolchains="envs clang gcc"
+ elif is_plat "mingw"; then
+ if is_arch "i386"; then
+ toolchains="i686_w64_mingw32"
+ else
+ toolchains="x86_64_w64_mingw32"
+ fi
+ else
+ toolchains="envs gcc clang"
+ fi
+ fi
+ for toolchain in ${toolchains}; do
+ if _toolchain_try "$toolchain"; then
+ _target_toolchain=${toolchain}
+ break
+ fi
+ done
+}
+
+# check toolchain
+_check_toolchain() {
+ local toolchain=${_target_toolchain}
+ _target_toolchain=""
+ _toolchain_detect ${toolchain}
+
+ if test "x${_target_toolchain}" != "x"; then
+ echo "checking for toolchain ... ${_target_toolchain}"
+ else
+ echo "checking for toolchain ... no"
+ raise "toolchain not found!"
+ fi
+}
+
+# get function code
+#
+# sigsetjmp
+# sigsetjmp((void*)0, 0)
+#
+_get_funccode() {
+ local func="${1}"
+ local code=""
+ if string_contains "${func}" "("; then
+ code="${func}"
+ else
+ code="volatile void* p${func} = (void*)&${func};"
+ fi
+ _ret="${code}"
+}
+
+# generate cxsnippets source code
+_generate_cxsnippets_sourcecode() {
+ local funcs="${1}"
+ local includes="${2}"
+ local types="${3}"
+ local snippets="${4}"
+
+ local snippet_includes=""
+ for include in $includes; do
+ snippet_includes="${snippet_includes}#include \"${include}\"\n"
+ done
+
+ local snippet_types=""
+ for type in $types; do
+ string_replace "${type}" '[^a-zA-Z]' "_"; local typevar="${_ret}"
+ snippet_types="${snippet_types}typedef ${type} __type_${typevar};\n"
+ done
+
+ local snippet_funcs=""
+ for func in $funcs; do
+ _get_funccode "${func}"; func="${_ret}"
+ snippet_funcs="${snippet_funcs}${func}\n "
+ done
+
+ local snippets_code=""
+ if test_nz "${snippet_includes}"; then
+ snippets_code="${snippets_code}${snippet_includes}\n"
+ fi
+ if test_nz "${snippet_types}"; then
+ snippets_code="${snippets_code}${snippet_types}\n"
+ fi
+ if test_nz "${snippets}"; then
+ snippets_code="${snippets_code}${snippets}\n"
+ fi
+
+ _ret='
+'"${snippets_code}"'int main(int argc, char** argv) {
+ '"${snippet_funcs}"'
+ return 0;
+}'
+}
+
+# check cxsnippets
+_check_cxsnippets() {
+ local name="${1}"
+ local kind="${2}"
+ _get_option_item "${name}" "${kind}funcs"; local funcs="${_ret}"
+ _get_option_item "${name}" "${kind}includes"; local includes="${_ret}"
+ _get_option_item "${name}" "${kind}types"; local types="${_ret}"
+ _get_option_item "${name}" "${kind}snippets"; local snippets="${_ret}"
+ _get_option_item "${name}" "links"; local links="${_ret}"
+ _get_option_item "${name}" "syslinks"; local syslinks="${_ret}"
+ if test_z "${funcs}" && test_z "${includes}" &&
+ test_z "${types}" && test_z "${snippets}"; then
+ return 0
+ fi
+ if test_nz "${syslinks}"; then
+ links="${links} ${syslinks}"
+ fi
+
+ # get c/c++ extension
+ local extension=".c"
+ local sourcekind="cc"
+ if test_eq "${kind}" "cxx"; then
+ extension=".cpp"
+ sourcekind="cxx"
+ fi
+
+ # generate source code
+ _generate_cxsnippets_sourcecode "${funcs}" "${includes}" "${types}" "${snippets}"; local sourcecode="${_ret}"
+ dprint "${sourcecode}"
+
+ # generate the source file
+ _os_tmpfile
+ local tmpfile="${_ret}"
+ local sourcefile="${tmpfile}${extension}"
+ local objectfile="${tmpfile}.o"
+ local binaryfile="${tmpfile}.bin"
+ print "${sourcecode}" > "${sourcefile}"
+
+ # try compiling it
+ local ok=false
+ if ! ${ok}; then
+ local compflags=""
+ _get_toolchain_toolset "${_target_toolchain}" "${sourcekind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ local itemnames="languages warnings optimizes defines undefines"
+ for itemname in ${itemnames}; do
+ _get_option_abstract_flags "${name}" "${sourcekind}" "${toolname}" "${itemname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ _split_flags "${flags}"; flags="${_ret}"
+ compflags="${compflags} ${flags}"
+ fi
+ done
+ local flagnames="cxflags"
+ if test_eq "${sourcekind}" "cxx"; then
+ flagnames="${flagnames} cxxflags"
+ else
+ flagnames="${flagnames} cflags"
+ fi
+ for flagname in $flagnames; do
+ _get_option_item "${name}" "${flagname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ compflags="${compflags} ${flags}"
+ fi
+ done
+ _toolchain_compcmd "${sourcekind}" "${objectfile}" "${sourcefile}" "${compflags}"; local compcmd="${_ret}"
+ if ${xmake_sh_diagnosis}; then
+ print "> ${compcmd}"
+ fi
+ if _os_runv ${compcmd}; then
+ ok=true
+ fi
+ fi
+
+ # try linking it
+ if ${ok} && test_nz "${links}"; then
+ local toolkind="ld"
+ _get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ local itemnames="linkdirs links syslinks"
+ local linkflags=""
+ for itemname in ${itemnames}; do
+ _get_option_abstract_flags "${name}" "${toolkind}" "${toolname}" "${itemname}"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ _split_flags "${flags}"; flags="${_ret}"
+ linkflags="${linkflags} ${flags}"
+ fi
+ done
+ _get_option_item "${name}" "ldflags"; local flags="${_ret}"
+ if test_nz "${flags}"; then
+ linkflags="${linkflags} ${flags}"
+ fi
+ _toolchain_linkcmd "${toolkind}" "${binaryfile}" "${objectfile}" "${linkflags}"; local linkcmd="${_ret}"
+ if ${xmake_sh_diagnosis}; then
+ print "> ${linkcmd}"
+ fi
+ if _os_runv ${linkcmd}; then
+ ok=true
+ else
+ ok=false
+ fi
+ fi
+
+ # trace
+ if ${xmake_sh_verbose} || ${xmake_sh_diagnosis}; then
+ if test_nz "${includes}"; then
+ print "> checking for ${kind} includes(${includes})"
+ fi
+ if test_nz "${types}"; then
+ print "> checking for ${kind} types(${types})"
+ fi
+ if test_nz "${funcs}"; then
+ print "> checking for ${kind} funcs(${funcs})"
+ fi
+ if test_nz "${links}"; then
+ print "> checking for ${kind} links(${links})"
+ fi
+ fi
+
+ # remove files
+ _os_tryrm "${sourcefile}"
+ _os_tryrm "${objectfile}"
+ _os_tryrm "${binaryfile}"
+ if ${ok}; then
+ return 0
+ fi
+ return 1
+}
+
+# check csnippets
+_check_csnippets() {
+ local name="${1}"
+ if _check_cxsnippets "${name}" "c"; then
+ return 0
+ fi
+ return 1
+}
+
+# check cxxsnippets
+_check_cxxsnippets() {
+ local name="${1}"
+ if _check_cxsnippets "${name}" "cxx"; then
+ return 0
+ fi
+ return 1
+}
+
+# check option
+_check_option() {
+ local name="${1}"
+ if _check_csnippets "${name}" && _check_cxxsnippets "${name}"; then
+ return 0
+ fi
+ return 1
+}
+
+# check options
+_check_options() {
+ _get_options_for_checking; local options="${_ret}"
+ for name in $options; do
+ if _check_option "$name"; then
+ echo "checking for ${name} .. ok"
+ _set_option_value "${name}" true
+ else
+ echo "checking for ${name} .. no"
+ _set_option_value "${name}" false
+ fi
+ done
+}
+
+# check all
+_check_all() {
+ _check_platform
+ _check_toolchain
+ _check_options
+}
+_check_all
+
+#-----------------------------------------------------------------------------
+# init builtin variables, e.g. add_headerfiles "${buildir}/config.h"
+#
+projectdir="${xmake_sh_projectdir}"
+if path_is_absolute "${xmake_sh_buildir}"; then
+ buildir="${xmake_sh_buildir}"
+else
+ buildir="${xmake_sh_projectdir}/${xmake_sh_buildir}"
+fi
+plat="${_target_plat}"
+arch="${_target_arch}"
+mode="${_target_mode}"
+
+#-----------------------------------------------------------------------------
+# load project targets
+#
+
+# load targets
+_load_targets() {
+ _loading_options=false
+ _loading_toolchains=false
+ _loading_targets=true
+ _xmake_sh_option_current=""
+ _xmake_sh_target_current=""
+ _xmake_sh_toolchain_current=""
+ local file=${xmake_sh_projectdir}/xmake.sh
+ if test -f "${file}"; then
+ includes "${file}"
+ else
+ # include all xmake.sh files in next sub-directories
+ _os_find "${xmake_sh_projectdir}" "xmake.sh" 2; local files="${_ret}"
+ for file in ${files}; do
+ includes "${file}"
+ done
+ fi
+}
+_load_targets
+
+# get toolset kinds for all targets
+# e.g. cc cxx as mm mxx ld sh ar
+_get_targets_toolkinds() {
+ if test_z "${_targets_toolkinds_dedup}"; then
+ _dedup "${_targets_toolkinds}"; _targets_toolkinds_dedup="${_ret}"
+ fi
+ _ret="${_targets_toolkinds_dedup}"
+}
+
+#-----------------------------------------------------------------------------
+# generate configfiles
+#
+
+# vprint config variable in `${name}`
+_vprint_configvar_value() {
+ local name="${1}"
+ local value="${2}"
+ vprint " > replace ${name} -> ${value}"
+}
+
+# vprint config variable in `${define name}`
+_vprint_configvar_define() {
+ local name="${1}"
+ local value="${2}"
+ if test_z "${value}"; then
+ vprint " > replace ${name} -> /* #undef ${name} */"
+ elif test_eq "${value}" "1" || test_eq "${value}" "true"; then
+ vprint " > replace ${name} -> #define ${name} 1"
+ elif test_eq "${value}" "0" || test_eq "${value}" "false"; then
+ vprint " > replace ${name} -> /*#define ${name} 0*/"
+ else
+ vprint " > replace ${name} -> #define ${name} ${value}"
+ fi
+}
+
+# replace config variable in `${define name}`
+_replace_configvar_define() {
+ local name="${1}"
+ local value="${2}"
+ if test_z "${value}"; then
+ _ret="s/\${define ${name}}/\/*#undef ${name}*\//g"
+ elif test_eq "${value}" "1" || test_eq "${value}" "true"; then
+ _ret="s/\${define ${name}}/#define ${name} 1/g"
+ elif test_eq "${value}" "0" || test_eq "${value}" "false"; then
+ _ret="s/\${define ${name}}/\/*#define ${name} 0*\//g"
+ else
+ _ret="s/\${define ${name}}/#define ${name} ${value}/g"
+ fi
+}
+
+# replace config variable in `${name}`
+_replace_configvar_value() {
+ local name="${1}"
+ local value="${2}"
+ _ret="s/\${${name}}/${value}/g"
+}
+
+# generate configfile for the given target
+_generate_configfile() {
+ local target="${1}"
+ local configfile_in="${2}"
+ _get_target_item "${target}" "configdir"; local configdir="${_ret}"
+ if test_z "${configdir}"; then
+ path_directory configfile_in; configdir="${_ret}"
+ fi
+ if ! test -d "${configdir}"; then
+ mkdir -p "${configdir}"
+ fi
+ path_basename "${configfile_in}"; local filename="${_ret}"
+ local configfile="${configdir}/${filename}"
+ echo "generating ${configfile} .."
+
+ # replace builtin variables
+ local patterns=""
+ local target_os=""
+ if is_plat "mingw"; then
+ target_os="windows"
+ else
+ target_os="${_target_plat}"
+ fi
+ string_toupper ${target_os}; target_os="${_ret}"
+ _vprint_configvar_value "OS" "${target_os}"
+ _replace_configvar_value "OS" "${target_os}"; patterns="${_ret};${patterns}"
+
+ # replace version
+ _get_target_item "${target}" "version"; local version="${_ret}"
+ _get_target_item "${target}" "version_build"; local version_build="${_ret}"
+ string_split "${version}" "."
+ local version_major="${_ret}"
+ local version_minor="${_ret2}"
+ local version_alter="${_ret3}"
+ if test_nz "${version}"; then
+ _vprint_configvar_value "VERSION" "${version}"
+ _replace_configvar_value "VERSION" "${version}"; patterns="${_ret};${patterns}"
+ fi
+ if test_nz "${version_major}"; then
+ _vprint_configvar_value "VERSION_MAJOR" "${version_major}"
+ _replace_configvar_value "VERSION_MAJOR" "${version_major}"; patterns="${_ret};${patterns}"
+ fi
+ if test_nz "${version_minor}"; then
+ _vprint_configvar_value "VERSION_MINOR" "${version_minor}"
+ _replace_configvar_value "VERSION_MINOR" "${version_minor}"; patterns="${_ret};${patterns}"
+ fi
+ if test_nz "${version_alter}"; then
+ _vprint_configvar_value "VERSION_ALTER" "${version_alter}"
+ _replace_configvar_value "VERSION_ALTER" "${version_alter}"; patterns="${_ret};${patterns}"
+ fi
+ if test_nz "${version_build}"; then
+ _os_date "${version_build}"; version_build="${_ret}"
+ _vprint_configvar_value "VERSION_BUILD" "${version_build}"
+ _replace_configvar_value "VERSION_BUILD" "${version_build}"; patterns="${_ret};${patterns}"
+ fi
+
+ # replace git variables
+ local content=$(cat "${configfile_in}")
+ if string_contains "${content}" "GIT_"; then
+ _os_iorunv "git" "describe" "--tags"; local git_tag="${_ret}"
+ if test_nz "${git_tag}"; then
+ _vprint_configvar_value "GIT_TAG" "${git_tag}"
+ _replace_configvar_value "GIT_TAG" "${git_tag}"; patterns="${_ret};${patterns}"
+ fi
+ _os_iorunv "git" "describe" "--tags" "--long"; local git_tag_long="${_ret}"
+ if test_nz "${git_tag_long}"; then
+ _vprint_configvar_value "GIT_TAG_LONG" "${git_tag_long}"
+ _replace_configvar_value "GIT_TAG_LONG" "${git_tag_long}"; patterns="${_ret};${patterns}"
+ fi
+ _os_iorunv "git" "rev-parse" "--abbrev-ref" "HEAD"; local git_branch="${_ret}"
+ if test_nz "${git_branch}"; then
+ _vprint_configvar_value "GIT_BRANCH" "${git_branch}"
+ _replace_configvar_value "GIT_BRANCH" "${git_branch}"; patterns="${_ret};${patterns}"
+ fi
+ _os_iorunv "git" "rev-parse" "--short" "HEAD"; local git_commit="${_ret}"
+ if test_nz "${git_commit}"; then
+ _vprint_configvar_value "GIT_COMMIT" "${git_commit}"
+ _replace_configvar_value "GIT_COMMIT" "${git_commit}"; patterns="${_ret};${patterns}"
+ fi
+ _os_iorunv "git" "rev-parse" "HEAD"; local git_commit_long="${_ret}"
+ if test_nz "${git_commit_long}"; then
+ _vprint_configvar_value "GIT_COMMIT_LONG" "${git_commit_long}"
+ _replace_configvar_value "GIT_COMMIT_LONG" "${git_commit_long}"; patterns="${_ret};${patterns}"
+ fi
+ _os_iorunv "log" "-1" "--date=format:%Y%m%d%H%M%S" "--format=%ad"; local git_commit_date="${_ret}"
+ if test_nz "${git_commit_date}"; then
+ _vprint_configvar_value "GIT_COMMIT_DATE" "${git_commit_date}"
+ _replace_configvar_value "GIT_COMMIT_DATE" "${git_commit_date}"; patterns="${_ret};${patterns}"
+ fi
+ fi
+
+ # replace configvars in target
+ local count=0
+ local configfile_dst="${configfile}"
+ _os_tmpfile; local tmpfile="${_ret}"
+ cp "${configfile_in}" "${tmpfile}"
+ _get_target_item "${target}" "configvars"; local configvars="${_ret}"
+ for name in ${configvars}; do
+ _get_target_item "${target}" "configvar_${name}"; local value="${_ret}"
+ _vprint_configvar_define "${name}" "${value}"
+ _vprint_configvar_value "${name}" "${value}"
+ _replace_configvar_define "${name}" "${value}"; patterns="${_ret};${patterns}"
+ _replace_configvar_value "${name}" "${value}"; patterns="${_ret};${patterns}"
+ count=$((count + 1))
+
+ # do replace
+ if test_eq "$count" "10"; then
+ _io_replace_file "${tmpfile}" "${configfile}" "${patterns}"
+ local swapfile="${tmpfile}"
+ tmpfile="${configfile}"
+ configfile="${swapfile}"
+ patterns=""
+ count=0
+ fi
+ done
+
+ # do replace (left)
+ if test_nz "${patterns}"; then
+ _io_replace_file "${tmpfile}" "${configfile}" "${patterns}"
+ local swapfile="${tmpfile}"
+ tmpfile="${configfile}"
+ configfile="${swapfile}"
+ patterns=""
+ count=0
+ fi
+
+ # replace fallback
+ patterns='s/${define \(.*\)}/\/*#undef \1*\//g;'
+ _io_replace_file "${tmpfile}" "${configfile}" "${patterns}"
+ if test_nq "${configfile}" "${configfile_dst}"; then
+ cp "${configfile}" "${configfile_dst}"
+ fi
+ echo "${configfile_dst} is generated!"
+}
+
+# generate configfiles
+_generate_configfiles() {
+ for target in ${_xmake_sh_targets}; do
+ _get_target_item "${target}" "configfiles"; local configfiles="${_ret}"
+ for configfile in ${configfiles}; do
+ _generate_configfile "${target}" "${configfile}"
+ done
+ done
+}
+_generate_configfiles
+
+#-----------------------------------------------------------------------------
+# generate gmake file
+#
+
+_gmake_begin() {
+ echo "generating makefile .."
+}
+
+_gmake_add_header() {
+ echo "# this is the build file for this project
+# it is autogenerated by the xmake.sh build system.
+# do not edit by hand.
+" > "${xmake_sh_makefile}"
+}
+
+_gmake_add_switches() {
+ echo "ifneq (\$(VERBOSE),1)" >> "${xmake_sh_makefile}"
+ echo "V=@" >> "${xmake_sh_makefile}"
+ echo "endif" >> "${xmake_sh_makefile}"
+ echo "" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_flags() {
+ _get_targets_toolkinds; local kinds="${_ret}"
+ for target in ${_xmake_sh_targets}; do
+ for kind in ${kinds}; do
+ _get_target_flags "${target}" "${kind}"; local flags="${_ret}"
+ _get_flagname "${kind}"; local flagname="${_ret}"
+ local key="${target}_${flagname}"
+ echo "${key}=${flags}" >> "${xmake_sh_makefile}"
+ done
+ echo "" >> "${xmake_sh_makefile}"
+ done
+}
+
+_gmake_add_toolchains() {
+ _get_targets_toolkinds; local kinds="${_ret}"
+ for kind in ${kinds}; do
+ _get_toolchain_toolset "${_target_toolchain}" "${kind}"; local program="${_ret}"
+ local key="${kind}"
+ echo "${key}=${program}" >> "${xmake_sh_makefile}"
+ done
+ echo "" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_build_object_for_gcc_clang() {
+ local kind="${1}"
+ local sourcefile="${2}"
+ local objectfile="${3}"
+ local flagname="${4}"
+ path_directory "${objectfile}"; local objectdir="${_ret}"
+ print "\t@mkdir -p ${objectdir}" >> "${xmake_sh_makefile}"
+ print "\t\$(V)\$(${kind}) -c \$(${flagname}) -o ${objectfile} ${sourcefile}" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_build_object() {
+ local target=${1}
+ local sourcefile="${2}"
+ local objectfile="${3}"
+ path_sourcekind "${sourcefile}"; local sourcekind="${_ret}"
+ _get_toolchain_toolset "${_target_toolchain}" "${sourcekind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+ _get_flagname "${sourcekind}"; local flagname="${_ret}"
+ flagname="${target}_${flagname}"
+ echo "${objectfile}: ${sourcefile}" >> "${xmake_sh_makefile}"
+ print "\t@echo compiling.${_target_mode} ${sourcefile}" >> "${xmake_sh_makefile}"
+ case "${toolname}" in
+ gcc) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
+ gxx) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
+ clang) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
+ clangxx) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
+ *) raise "unknown toolname(${toolname})!" ;;
+ esac
+ echo "" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_build_objects() {
+ local target=${1}
+ _get_target_sourcefiles "${target}"; local sourcefiles="${_ret}"
+ for sourcefile in ${sourcefiles}; do
+ _get_target_objectfile "${target}" "${sourcefile}"; local objectfile="${_ret}"
+ _gmake_add_build_object "${target}" "${sourcefile}" "${objectfile}"
+ done
+}
+
+_gmake_add_build_target_for_gcc_clang() {
+ local kind="${1}"
+ local targetfile="${2}"
+ local objectfiles="${3}"
+ local flagname="${4}"
+ path_directory "${targetfile}"; local targetdir="${_ret}"
+ print "\t@mkdir -p ${targetdir}" >> "${xmake_sh_makefile}"
+ print "\t\$(V)\$(${kind}) -o ${targetfile} ${objectfiles} \$(${flagname})" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_build_target_for_ar() {
+ local kind="${1}"
+ local targetfile="${2}"
+ local objectfiles="${3}"
+ local flagname="${4}"
+ path_directory "${targetfile}"; local targetdir="${_ret}"
+ print "\t@mkdir -p ${targetdir}" >> "${xmake_sh_makefile}"
+ print "\t\$(V)\$(${kind}) \$(${flagname}) ${flags} ${targetfile} ${objectfiles}" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_build_target() {
+ local target=${1}
+ _get_targetdir "${target}"; local targetdir="${_ret}"
+ _get_target_file "${target}"; local targetfile="${_ret}"
+ _get_target_item "${target}" "deps"; local deps="${_ret}"
+ _get_target_objectfiles "${target}"; local objectfiles="${_ret}"
+
+ # get linker
+ _get_target_item "${target}" "kind"; local targetkind="${_ret}"
+ local toolkind=""
+ case "${targetkind}" in
+ binary) toolkind="ld";;
+ static) toolkind="ar";;
+ shared) toolkind="sh";;
+ *) raise "unknown targetkind(${targetkind})!" ;;
+ esac
+ _get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
+ path_toolname "${program}"; local toolname="${_ret}"
+
+ # get linker flags
+ _get_flagname "${toolkind}"; local flagname="${_ret}"
+ flagname="${target}_${flagname}"
+
+ # link target
+ echo "${target}: ${targetfile}" >> "${xmake_sh_makefile}"
+ echo "${targetfile}: ${deps}${objectfiles}" >> "${xmake_sh_makefile}"
+ print "\t@echo linking.${_target_mode} ${targetfile}" >> "${xmake_sh_makefile}"
+ case "${toolname}" in
+ gcc) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
+ gxx) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
+ clang) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
+ clangxx) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
+ ar) _gmake_add_build_target_for_ar "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
+ *) raise "unknown toolname(${toolname})!" ;;
+ esac
+ echo "" >> "${xmake_sh_makefile}"
+
+ # build objects
+ _gmake_add_build_objects "${target}"
+}
+
+_gmake_add_build_targets() {
+ local defaults=""
+ for target in ${_xmake_sh_targets}; do
+ if _is_target_default "${target}"; then
+ defaults="${defaults} ${target}"
+ fi
+ done
+ echo "default:${defaults}" >> "${xmake_sh_makefile}"
+ echo "all:${_xmake_sh_targets}" >> "${xmake_sh_makefile}"
+ echo ".PHONY: default all" >> "${xmake_sh_makefile}"
+ echo "" >> "${xmake_sh_makefile}"
+ for target in ${_xmake_sh_targets}; do
+ _gmake_add_build_target "${target}"
+ done
+}
+
+_gmake_add_build() {
+ _gmake_add_build_targets
+}
+
+_gmake_add_run_target() {
+ local target=${1}
+ _get_target_file "${target}"; local targetfile="${_ret}"
+ print "\t@${targetfile}" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_run_targets() {
+ local targets=""
+ for target in ${_xmake_sh_targets}; do
+ _get_target_item "${target}" "kind"; local kind="${_ret}"
+ if test "x${kind}" = "xbinary"; then
+ if _is_target_default "${target}"; then
+ targets="${targets} ${target}"
+ fi
+ fi
+ done
+ echo "run:${targets}" >> "${xmake_sh_makefile}"
+ for target in ${targets}; do
+ _gmake_add_run_target "${target}"
+ done
+ echo "" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_run() {
+ _gmake_add_run_targets
+}
+
+_gmake_add_clean_target() {
+ local target=${1}
+ _get_target_file "${target}"; local targetfile="${_ret}"
+ _get_target_objectfiles "${target}"; local objectfiles="${_ret}"
+ print "\t@rm ${targetfile}" >> "${xmake_sh_makefile}"
+ for objectfile in ${objectfiles}; do
+ print "\t@rm ${objectfile}" >> "${xmake_sh_makefile}"
+ done
+}
+
+_gmake_add_clean_targets() {
+ local targets=""
+ for target in ${_xmake_sh_targets}; do
+ if _is_target_default "${target}"; then
+ targets="${targets} ${target}"
+ fi
+ done
+ echo "clean:${targets}" >> "${xmake_sh_makefile}"
+ for target in ${targets}; do
+ _gmake_add_clean_target "${target}"
+ done
+ echo "" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_clean() {
+ _gmake_add_clean_targets
+}
+
+_gmake_add_install_target() {
+ local target=${1}
+ _get_target_file "${target}"; local targetfile="${_ret}"
+ path_filename "${targetfile}"; local filename="${_ret}"
+ _get_target_item "${target}" "installdir"; local installdir="${_ret}"
+ if test_z "${installdir}"; then
+ installdir=${_install_prefix_default}
+ fi
+
+ # install target file
+ _get_target_item "${target}" "kind"; local targetkind="${_ret}"
+ if test_eq "${targetkind}" "binary"; then
+ print "\t@mkdir -p ${installdir}/${_install_bindir_default}" >> "${xmake_sh_makefile}"
+ print "\t@cp -p ${targetfile} ${installdir}/${_install_bindir_default}/${filename}" >> "${xmake_sh_makefile}"
+ elif test_eq "${targetkind}" "static" || test_eq "${targetkind}" "shared"; then
+ print "\t@mkdir -p ${installdir}/${_install_libdir_default}" >> "${xmake_sh_makefile}"
+ print "\t@cp -p ${targetfile} ${installdir}/${_install_libdir_default}/${filename}" >> "${xmake_sh_makefile}"
+ fi
+
+ # install header files
+ _get_target_item "${target}" "headerfiles"; local headerfiles="${_ret}"
+ if test_nz "${headerfiles}"; then
+ local includedir="${installdir}/${_install_includedir_default}"
+ for srcheaderfile in ${headerfiles}; do
+ string_split "${srcheaderfile}" ":"
+ local srcheaderfile="${_ret}"
+ local rootdir="${_ret2}"
+ local prefixdir="${_ret3}"
+ path_filename "${srcheaderfile}"; local filename="${_ret}"
+ local dstheaderdir="${includedir}"
+ if test_nz "${prefixdir}"; then
+ dstheaderdir="${dstheaderdir}/${prefixdir}"
+ fi
+ local dstheaderfile="${dstheaderdir}/${filename}"
+ if test_nz "${rootdir}"; then
+ path_relative "${rootdir}" "${srcheaderfile}"; local subfile="${_ret}"
+ dstheaderfile="${dstheaderdir}/${subfile}"
+ fi
+ path_directory "${dstheaderfile}"; dstheaderdir="${_ret}"
+ print "\t@mkdir -p ${dstheaderdir}" >> "${xmake_sh_makefile}"
+ print "\t@cp -p ${srcheaderfile} ${dstheaderfile}" >> "${xmake_sh_makefile}"
+ done
+ fi
+
+ # install user files
+ _get_target_item "${target}" "installfiles"; local installfiles="${_ret}"
+ if test_nz "${installfiles}"; then
+ for srcinstallfile in ${installfiles}; do
+ string_split "${srcinstallfile}" ":"
+ local srcinstallfile="${_ret}"
+ local rootdir="${_ret2}"
+ local prefixdir="${_ret3}"
+ path_filename "${srcinstallfile}"; local filename="${_ret}"
+ local dstinstalldir="${installdir}"
+ if test_nz "${prefixdir}"; then
+ dstinstalldir="${dstinstalldir}/${prefixdir}"
+ fi
+ local dstinstallfile="${dstinstalldir}/${filename}"
+ if test_nz "${rootdir}"; then
+ path_relative "${rootdir}" "${srcinstallfile}"; local subfile="${_ret}"
+ dstinstallfile="${dstinstalldir}/${subfile}"
+ fi
+ path_directory "${dstinstallfile}"; dstinstalldir="${_ret}"
+ print "\t@mkdir -p ${dstinstalldir}" >> "${xmake_sh_makefile}"
+ print "\t@cp -p ${srcinstallfile} ${dstinstallfile}" >> "${xmake_sh_makefile}"
+ done
+ fi
+}
+
+_gmake_add_install_targets() {
+ local targets=""
+ for target in ${_xmake_sh_targets}; do
+ if _is_target_default "${target}"; then
+ targets="${targets} ${target}"
+ fi
+ done
+ echo "install:${targets}" >> "${xmake_sh_makefile}"
+ for target in ${targets}; do
+ _gmake_add_install_target "${target}"
+ done
+ echo "" >> "${xmake_sh_makefile}"
+}
+
+_gmake_add_install() {
+ _gmake_add_install_targets
+}
+
+_gmake_done() {
+ echo "makefile is generated!"
+}
+
+# generate build file for gmake
+_generate_for_gmake() {
+ _gmake_begin
+ _gmake_add_header
+ _gmake_add_switches
+ _gmake_add_toolchains
+ _gmake_add_flags
+ _gmake_add_build
+ _gmake_add_clean
+ _gmake_add_install
+ _gmake_add_run
+ _gmake_done
+}
+
+#-----------------------------------------------------------------------------
+# generate ninja file
+#
+
+# generate build file for ninja
+_generate_for_ninja() {
+ raise "Ninja generator has been not supported!"
+}
+
+#-----------------------------------------------------------------------------
+# generate build file
+#
+
+_generate_build_file() {
+ if test_eq "${_project_generator}" "gmake"; then
+ _generate_for_gmake
+ elif test_eq "${_project_generator}" "ninja"; then
+ _generate_for_ninja
+ else
+ raise "unknown generator: ${_project_generator}"
+ fi
+}
+_generate_build_file
+
+
diff --git a/core/src/demo/xmake.lua b/core/src/demo/xmake.lua
index 1e33415ae..34bf4c0d2 100644
--- a/core/src/demo/xmake.lua
+++ b/core/src/demo/xmake.lua
@@ -31,7 +31,7 @@ target("demo")
add_ldflags("/export:malloc", "/export:free", "/export:memmove")
elseif is_plat("android") then
add_links("m", "c")
- elseif is_plat("macosx") then
+ elseif is_plat("macosx") and is_config("runtime", "luajit") then
add_ldflags("-all_load", "-pagezero_size 10000", "-image_base 100000000")
elseif is_plat("mingw") then
add_ldflags("-static-libgcc", {force = true})
diff --git a/core/src/demo/xmake.sh b/core/src/demo/xmake.sh
new file mode 100755
index 000000000..be352f1f0
--- /dev/null
+++ b/core/src/demo/xmake.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+target "demo"
+ add_deps "xmake"
+ set_kind "binary"
+ set_basename "xmake"
+ set_targetdir "${buildir}"
+
+ # add defines
+ add_defines "__tb_prefix__=\"xmake\""
+
+ # add includes directory
+ add_includedirs "${projectdir}/core" "${projectdir}/core/src"
+
+ # add the common source files
+ add_files "**.c"
+
+ # add links
+ if is_plat "macosx" && is_config "runtime" "luajit"; then
+ add_ldflags "-all_load" "-pagezero_size 10000" "-image_base 100000000"
+ elif is_plat "mingw"; then
+ add_ldflags "-static-libgcc"
+ fi
+
+
diff --git a/core/src/lua-cjson/xmake.lua b/core/src/lua-cjson/xmake.lua
index 75b62c16b..74406d67e 100644
--- a/core/src/lua-cjson/xmake.lua
+++ b/core/src/lua-cjson/xmake.lua
@@ -1,7 +1,7 @@
target("lua-cjson")
set_kind("static")
set_warnings("all")
- add_deps(get_config("runtime"))
+ add_deps("lua")
if is_plat("windows") then
set_languages("c89")
end
diff --git a/core/src/lua-cjson/xmake.sh b/core/src/lua-cjson/xmake.sh
new file mode 100755
index 000000000..6b9e4aad3
--- /dev/null
+++ b/core/src/lua-cjson/xmake.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+target "lua_cjson"
+ set_kind "static"
+ set_warnings "all"
+ add_deps "lua"
+ add_files "lua-cjson/dtoa.c"
+ add_files "lua-cjson/lua_cjson.c"
+ add_files "lua-cjson/strbuf.c"
+ add_files "lua-cjson/g_fmt.c"
+ # Use internal strtod() / g_fmt() code for performance and disable multi-thread
+ add_defines "NDEBUG" "USE_INTERNAL_FPCONV"
+
diff --git a/core/src/lua/xmake.lua b/core/src/lua/xmake.lua
index 5d08083db..048d7305e 100644
--- a/core/src/lua/xmake.lua
+++ b/core/src/lua/xmake.lua
@@ -1,7 +1,4 @@
target("lua")
- if not is_config("runtime", "lua") then
- set_default(false)
- end
set_kind("static")
set_warnings("all")
diff --git a/core/src/lua/xmake.sh b/core/src/lua/xmake.sh
new file mode 100755
index 000000000..f9e190c16
--- /dev/null
+++ b/core/src/lua/xmake.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+target "lua"
+ set_kind "static"
+ set_warnings "all"
+
+ # add include directories
+ add_includedirs "lua" "{public}"
+
+ # add the common source files
+ add_files "lua/lapi.c"
+ add_files "lua/lauxlib.c"
+ add_files "lua/lbaselib.c"
+ add_files "lua/lcode.c"
+ add_files "lua/lcorolib.c"
+ add_files "lua/lctype.c"
+ add_files "lua/ldblib.c"
+ add_files "lua/ldebug.c"
+ add_files "lua/ldo.c"
+ add_files "lua/ldump.c"
+ add_files "lua/lfunc.c"
+ add_files "lua/lgc.c"
+ add_files "lua/linit.c"
+ add_files "lua/liolib.c"
+ add_files "lua/llex.c"
+ add_files "lua/lmathlib.c"
+ add_files "lua/lmem.c"
+ add_files "lua/loadlib.c"
+ add_files "lua/lobject.c"
+ add_files "lua/lopcodes.c"
+ add_files "lua/loslib.c"
+ add_files "lua/lparser.c"
+ add_files "lua/lstate.c"
+ add_files "lua/lstring.c"
+ add_files "lua/lstrlib.c"
+ add_files "lua/ltable.c"
+ add_files "lua/ltablib.c"
+ add_files "lua/ltm.c"
+ add_files "lua/lundump.c"
+ add_files "lua/lutf8lib.c"
+ add_files "lua/lvm.c"
+ add_files "lua/lzio.c"
+
+ # add defines
+ add_defines "LUA_COMPAT_5_1" "LUA_COMPAT_5_2" "LUA_COMPAT_5_3" "{public}"
+ if is_plat "mingw"; then
+ add_defines "LUA_USE_WINDOWS"
+ elif is_plat "macosx"; then
+ add_defines "LUA_USE_MACOSX"
+ else
+ add_defines "LUA_USE_LINUX"
+ fi
+
diff --git a/core/src/luajit/xmake.lua b/core/src/luajit/xmake.lua
index 427c319a1..8ad0bf1af 100644
--- a/core/src/luajit/xmake.lua
+++ b/core/src/luajit/xmake.lua
@@ -22,10 +22,7 @@ end
local autogendir = path.join("luajit", "autogen", plat, jit and "jit" or "nojit", arch)
-- add target
-target("luajit")
- if not is_config("runtime", "luajit") then
- set_default(false)
- end
+target("lua")
-- make as a static library
set_kind("static")
diff --git a/core/src/luajit/xmake.sh b/core/src/luajit/xmake.sh
new file mode 100755
index 000000000..e9a4222b0
--- /dev/null
+++ b/core/src/luajit/xmake.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+# disable jit compiler for redhat and centos
+jit=true
+jit_plat="${plat}"
+jit_arch="${arch}"
+if is_plat "mingw"; then
+ jit_plat="windows"
+ if is_arch "x86_64"; then
+ jit_arch="x64"
+ else
+ jit_arch="x86"
+ fi
+fi
+if is_arch "arm64" "arm64-v8a"; then
+ jit_arch="arm64"
+elif is_arch "arm" "armv7"; then
+ jit_arch="arm"
+elif is_arch "mips64"; then
+ jit_arch="mips64"
+ jit=false
+fi
+if test -f "/etc/redhat-release"; then
+ jit=false
+fi
+if $jit; then
+ jit_dir="jit"
+else
+ jit_dir="nojit"
+fi
+jit_autogendir="luajit/autogen/${jit_plat}/${jit_dir}/${jit_arch}"
+
+target "lua"
+ set_kind "static"
+ set_warnings "all"
+
+ # add include directories
+ add_includedirs "${jit_autogendir}"
+ add_includedirs "luajit/src" "{public}"
+
+ # add the common source files
+ add_files "luajit/src/lj_*.c"
+ add_files "luajit/src/lib_*.c"
+ if is_plat "mingw"; then
+ add_files "${jit_autogendir}/lj_vm.o"
+ else
+ add_files "${jit_autogendir}/*.S"
+ fi
+
+ add_defines "USE_LUAJIT" "{public}"
+
+ # disable jit compiler?
+ if ! $jit; then
+ add_defines "LUAJIT_DISABLE_JIT"
+ fi
+
+ # using internal memory management under armv7 gc will cause a crash when free strings in lua_close
+ if test_eq "${jit_arch}" "arm"; then
+ add_defines "LUAJIT_USE_SYSMALLOC"
+ fi
+
+ # fix call math.sin/log crash for fedora/i386/lj_vm.S with `LDFLAGS = -specs=/usr/lib/rpm/redhat/redhat-hardened-ld` in xmake.spec/%set_build_flags
+ if is_plat "linux" && is_arch "i386"; then
+ add_asflags "-fPIE"
+ add_ldflags "-fPIE"
+ fi
+
diff --git a/core/src/lz4/xmake.sh b/core/src/lz4/xmake.sh
new file mode 100755
index 000000000..4b04f0a1d
--- /dev/null
+++ b/core/src/lz4/xmake.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+target "lz4"
+ set_kind "static"
+ set_warnings "all"
+ add_includedirs "lz4/lib" "{public}"
+ add_files "lz4/lib/lz4.c"
+ add_files "lz4/lib/lz4frame.c"
+ add_files "lz4/lib/lz4hc.c"
+ add_files "lz4/lib/xxhash.c"
+ add_defines "XXH_NAMESPACE=LZ4_"
+
+
diff --git a/core/src/sv/xmake.sh b/core/src/sv/xmake.sh
new file mode 100755
index 000000000..a89d277e9
--- /dev/null
+++ b/core/src/sv/xmake.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+target "sv"
+ set_languages "c99"
+ set_kind "static"
+ add_includedirs "sv/include" "{public}"
+ add_files "sv/src/*.c"
+
diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox
-Subproject 149fa2795e69f087999b34e3fdb417a485ad187
+Subproject bee9e65c3549d03adb3a003a984c926d9dde334
diff --git a/core/src/tbox/xmake.sh b/core/src/tbox/xmake.sh
new file mode 100755
index 000000000..76d3ef61a
--- /dev/null
+++ b/core/src/tbox/xmake.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+set_config "hash" true
+set_config "charset" true
+set_config "force_utf8" true
+set_config "float" true
+set_config "demo" false
+
+includes "tbox/src"
+target_end
+
+set_configvar "TB_CONFIG_MODULE_HAVE_HASH" 1
+set_configvar "TB_CONFIG_MODULE_HAVE_CHARSET" 1
+set_configvar "TB_CONFIG_FORCE_UTF8" 1
+set_configvar "TB_CONFIG_TYPE_HAVE_FLOAT" 1
diff --git a/core/src/xmake/os/cpuinfo.c b/core/src/xmake/os/cpuinfo.c
index 1e7753940..ef92a2be4 100644
--- a/core/src/xmake/os/cpuinfo.c
+++ b/core/src/xmake/os/cpuinfo.c
@@ -134,7 +134,6 @@ static tb_float_t xm_os_cpuinfo_usagerate()
tb_float_t usagerate = 0;
if (tb_file_info("/proc/stat", tb_null))
{
- tb_bool_t ok = tb_false;
FILE* fp = fopen("/proc/stat", "r");
if (fp)
{
diff --git a/core/src/xmake/xmake.lua b/core/src/xmake/xmake.lua
index 1745313fa..e100832ba 100644
--- a/core/src/xmake/xmake.lua
+++ b/core/src/xmake/xmake.lua
@@ -1,11 +1,8 @@
target("xmake")
-
- -- make as a static library
set_kind("static")
-- add deps
- add_deps("sv", "lua-cjson", "lz4", "tbox")
- add_deps(get_config("runtime"))
+ add_deps("sv", "lua-cjson", "lua", "lz4", "tbox")
if is_plat("windows") and has_config("pdcurses") then
add_deps("pdcurses")
end
diff --git a/core/src/xmake/xmake.sh b/core/src/xmake/xmake.sh
new file mode 100755
index 000000000..29cb102ba
--- /dev/null
+++ b/core/src/xmake/xmake.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+target "xmake"
+ set_kind "static"
+
+ # add deps
+ add_deps "sv" "lua_cjson" "lua" "lz4" "tbox"
+
+ # add defines
+ add_defines "__tb_prefix__=\"xmake\""
+ if is_mode "debug"; then
+ add_defines "__tb_debug__" "{public}"
+ fi
+
+ # set the auto-generated config.h
+ set_configdir "${buildir}/${plat}/${arch}/${mode}"
+ add_configfiles "xmake.config.h.in"
+
+ # add includes directory
+ add_includedirs ".." "{public}"
+ add_includedirs "${buildir}/${plat}/${arch}/${mode}" "{public}"
+ add_includedirs "../xxhash"
+
+ # add the common source files
+ add_files "*.c"
+ add_files "base64/*.c"
+ add_files "bloom_filter/*.c"
+ add_files "curses/*.c"
+ add_files "fwatcher/*.c"
+ add_files "hash/*.c"
+ add_files "io/*.c"
+ add_files "libc/*.c"
+ add_files "lz4/*.c"
+ add_files "os/*.c"
+ add_files "path/*.c"
+ add_files "process/*.c"
+ add_files "readline/*.c"
+ add_files "sandbox/*.c"
+ add_files "semver/*.c"
+ add_files "string/*.c"
+ add_files "tty/*.c"
+ if is_plat "mingw"; then
+ add_files "winos/*.c"
+ fi
+
+ # enable readline
+ if has_config "readline"; then
+ add_defines "XM_CONFIG_API_HAVE_READLINE" "{public}"
+ add_links "readline" "{public}"
+ fi
+
+ # enable curses
+ if has_config "curses"; then
+ add_defines "XM_CONFIG_API_HAVE_CURSES" "{public}"
+ add_links "curses" "{public}"
+ fi
diff --git a/core/xmake.lua b/core/xmake.lua
index a8a29e2fd..5519bbecf 100644
--- a/core/xmake.lua
+++ b/core/xmake.lua
@@ -98,9 +98,11 @@ if is_plat("windows") then
end
-- add projects
-includes("src/lua-cjson", "src/sv", "src/lua", "src/lz4", "src/tbox", "src/xmake", "src/demo")
+includes("src/lua-cjson", "src/sv", "src/lz4", "src/tbox", "src/xmake", "src/demo")
if is_config("runtime", "luajit") then
includes("src/luajit")
+else
+ includes("src/lua")
end
if is_plat("windows") then
includes("src/pdcurses")
diff --git a/core/xmake.sh b/core/xmake.sh
new file mode 100755
index 000000000..2cb211e58
--- /dev/null
+++ b/core/xmake.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+set_project "xmake"
+set_version "2.7.3" "%Y%m%d%H%M"
+
+# set warning all
+set_warnings "all"
+
+# set language: c99
+set_languages "c99"
+
+# add defines
+add_defines "_GNU_SOURCE=1" "_FILE_OFFSET_BITS=64" "_LARGEFILE_SOURCE"
+
+# disable some compiler errors
+if is_plat "macosx"; then
+ add_cxflags "-Wno-error=deprecated-declarations" "-fno-strict-aliasing" "-Wno-error=nullability-completeness" "-Wno-error=parentheses-equality"
+fi
+
+# add build modes
+if is_mode "debug"; then
+ set_symbols "debug"
+ set_optimizes "none"
+else
+ set_strip "all"
+ set_symbols "hidden"
+ set_optimizes "smallest"
+fi
+
+# the runtime option, lua or luajit
+option "runtime" "Use luajit or lua runtime" "lua"
+
+# the readline option
+option "readline"
+ set_description "Enable or disable readline library"
+ add_links "readline"
+ add_cincludes "readline/readline.h"
+ add_cfuncs "readline"
+
+# the curses option
+option "curses"
+ set_description "Enable or disable curses library"
+ add_links "curses"
+ add_cincludes "curses.h"
+option_end
+
+# add projects
+includes "src/lua-cjson"
+includes "src/sv"
+includes "src/lz4"
+includes "src/tbox"
+includes "src/xmake"
+includes "src/demo"
+if is_config "runtime" "luajit"; then
+ includes "src/luajit"
+else
+ includes "src/lua"
+fi
+
+