summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-11-13 00:44:11 +0800
committerruki <[email protected]>2025-11-13 00:44:11 +0800
commitd265e8c94bde4cdc5bdb1f6bc268a8ccd79ab964 (patch)
tree166a4bc484ce6415a22d1128a0a99d2c23102e03
parentd4205f6eca2257d69db51089341490e369552180 (diff)
update xmake.sh
-rwxr-xr-xconfigure785
1 files changed, 754 insertions, 31 deletions
diff --git a/configure b/configure
index 5b5498fa1..b10303076 100755
--- a/configure
+++ b/configure
@@ -29,6 +29,7 @@ xmake_sh_verbose=false
xmake_sh_diagnosis=false
xmake_sh_copyright="Copyright (C) 2022-present Ruki Wang, https://xmake.io."
xmake_sh_makefile="${xmake_sh_projectdir}/Makefile"
+xmake_sh_ninjafile="${xmake_sh_projectdir}/build.ninja"
#-----------------------------------------------------------------------------
# some helper functions
@@ -101,7 +102,81 @@ string_tolower() {
}
string_replace() {
- _ret=$(echo "$1" | sed "s/${2}/${3}/g")
+ local src="${1}"
+ local search="${2}"
+ local replace="${3}"
+ if test_z "${search}"; then
+ _ret="${src}"
+ return
+ fi
+ local rest="${src}"
+ local result=""
+ local prefix=""
+ while :; do
+ case "${rest}" in
+ *"${search}"*)
+ prefix="${rest%%"${search}"*}"
+ result="${result}${prefix}${replace}"
+ rest="${rest#*"${search}"}"
+ ;;
+ *)
+ result="${result}${rest}"
+ break
+ ;;
+ esac
+ done
+ _ret="${result}"
+}
+
+# escape value for writing into ninja files
+_ninja_escape() {
+ local rest="${1}"
+ case "${rest}" in
+ *\$*)
+ local result=""
+ while :; do
+ case "${rest}" in
+ *\$*)
+ result="${result}${rest%%\$*}\$\$"
+ rest="${rest#*\$}"
+ ;;
+ *)
+ result="${result}${rest}"
+ break
+ ;;
+ esac
+ done
+ _ret="${result}"
+ ;;
+ *)
+ _ret="${rest}"
+ ;;
+ esac
+}
+
+_shell_escape_single_quotes() {
+ local value="${1}"
+ case "${value}" in
+ *"'"*)
+ local escaped=""
+ while :; do
+ case "${value}" in
+ *"'"*)
+ escaped="${escaped}${value%%\'*}'\"'\"'"
+ value="${value#*\'}"
+ ;;
+ *)
+ escaped="${escaped}${value}"
+ break
+ ;;
+ esac
+ done
+ _ret="'${escaped}'"
+ ;;
+ *)
+ _ret="'${value}'"
+ ;;
+ esac
}
# we avoid use `cut` command, because it's slow
@@ -181,7 +256,12 @@ string_startswith() {
string_dupch() {
local count=${1}
local ch=${2}
- printf %${count}s | tr " " "${ch}"
+ local result=""
+ while [ "${count:-0}" -gt 0 ]; do
+ result="${result}${ch}"
+ count=$((count - 1))
+ done
+ printf '%s' "${result}"
}
# replace file content
@@ -601,30 +681,15 @@ _map_set() {
# 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
-if echo "${os_host}" | grep Haiku >/dev/null 2>&1; then
- os_host="haiku"
-fi
+case "${os_host}" in
+ *cygwin*) os_host="cygwin" ;;
+ *mingw*|*msys*) os_host="msys" ;;
+ *darwin*) os_host="macosx" ;;
+ *linux*) os_host="linux" ;;
+ *freebsd*) os_host="freebsd" ;;
+ *bsd*) os_host="bsd" ;;
+ *haiku*) os_host="haiku" ;;
+esac
# determining host
# e.g.
@@ -838,7 +903,7 @@ _get_abstract_flag_for_gcc_clang() {
local flag=""
case "${itemname}" in
defines)
- string_replace "${value}" '"' '\\\"'; value="${_ret}"
+ string_replace "${value}" '"' '\"'; value="${_ret}"
flag="-D${value}"
;;
undefines) flag="-U${value}";;
@@ -2841,13 +2906,19 @@ _show_version() {
# --foo=yes => foo
_parse_argument_name() {
- _ret=$(echo "${1#*--}" | sed "s/${2-=[^=]*}$//")
- string_replace "${_ret}" "-" "_"
+ local arg="${1#--}"
+ case "${arg}" in
+ *=*) arg="${arg%%=*}" ;;
+ esac
+ string_replace "${arg}" "-" "_"
}
# --foo=yes => yes
_parse_argument_value() {
- _ret=$(echo "$1" | sed "s/^${2-[^=]*=}//")
+ case "${1}" in
+ *=*) _ret="${1#*=}" ;;
+ *) _ret="" ;;
+ esac
}
# parse input arguments
@@ -4515,9 +4586,661 @@ _generate_for_gmake() {
# generate ninja file
#
+_ninja_begin() {
+ echo "generating ninja build file .."
+}
+
+_ninja_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_ninjafile}"
+ echo "ninja_required_version = 1.3" >> "${xmake_sh_ninjafile}"
+ echo "builddir = ${xmake_sh_builddir}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+}
+
+_ninja_add_switches() {
+ local value=""
+ value="${_install_prefix_default}"; _ninja_escape "${value}"; value="${_ret}"
+ echo "prefix_default = ${value}" >> "${xmake_sh_ninjafile}"
+ value="${_install_bindir_default}"; _ninja_escape "${value}"; value="${_ret}"
+ echo "bindir_default = ${value}" >> "${xmake_sh_ninjafile}"
+ value="${_install_libdir_default}"; _ninja_escape "${value}"; value="${_ret}"
+ echo "libdir_default = ${value}" >> "${xmake_sh_ninjafile}"
+ value="${_install_includedir_default}"; _ninja_escape "${value}"; value="${_ret}"
+ echo "includedir_default = ${value}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+}
+
+_ninja_add_rules() {
+ echo "rule command" >> "${xmake_sh_ninjafile}"
+ echo " command = \$command" >> "${xmake_sh_ninjafile}"
+ echo " description = \$description" >> "${xmake_sh_ninjafile}"
+ echo " restat = \$restat" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+}
+
+_ninja_add_toolchains() {
+ _get_targets_toolkinds; local kinds="${_ret}"
+ if test_nz "${kinds}"; then
+ echo "# toolchain programs" >> "${xmake_sh_ninjafile}"
+ for kind in ${kinds}; do
+ _get_toolchain_toolset "${_target_toolchain}" "${kind}"; local program="${_ret}"
+ echo "${kind} = ${program}" >> "${xmake_sh_ninjafile}"
+ done
+ echo "" >> "${xmake_sh_ninjafile}"
+ fi
+}
+
+_ninja_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}"
+ if test_nz "${flags}"; then
+ _get_flagname "${kind}"; local flagname="${_ret}"
+ local key="${target}_${flagname}"
+ _ninja_escape "${flags}"; flags="${_ret}"
+ echo "${key} = ${flags}" >> "${xmake_sh_ninjafile}"
+ fi
+ done
+ echo "" >> "${xmake_sh_ninjafile}"
+ done
+}
+
+_ninja_add_build_object() {
+ local target=${1}
+ local sourcefile="${2}"
+ local objectfile="${3}"
+ path_sourcekind "${sourcefile}"; local sourcekind="${_ret}"
+ _get_target_flags "${target}" "${sourcekind}"; local flags="${_ret}"
+ _toolchain_compcmd "${sourcekind}" "${objectfile}" "${sourcefile}" "${flags}"; local compcmd="${_ret}"
+ path_directory "${objectfile}"; local objectdir="${_ret}"
+ local command=""
+ local use_shell_wrapper=false
+ if is_host "msys" "cygwin" "mingw"; then
+ use_shell_wrapper=true
+ command="mkdir -p \"${objectdir}\" && ${compcmd}"
+ else
+ command="mkdir -p \"${objectdir}\" && ${compcmd}"
+ fi
+ if ${use_shell_wrapper}; then
+ _shell_escape_single_quotes "${command}"; local command_script="${_ret}"
+ command="sh -lc ${command_script}"
+ fi
+ local description="compiling.${_target_mode} ${sourcefile}"
+ _ninja_escape "${command}"; command="${_ret}"
+ _ninja_escape "${description}"; description="${_ret}"
+ echo "build ${objectfile}: command ${sourcefile}" >> "${xmake_sh_ninjafile}"
+ echo " command = ${command}" >> "${xmake_sh_ninjafile}"
+ echo " description = ${description}" >> "${xmake_sh_ninjafile}"
+ echo " restat = 0" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+}
+
+_ninja_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}"
+ _ninja_add_build_object "${target}" "${sourcefile}" "${objectfile}"
+ done
+}
+
+_ninja_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_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_target_flags "${target}" "${toolkind}"; local linkflags="${_ret}"
+ _toolchain_linkcmd "${toolkind}" "${targetfile}" "${objectfiles}" "${linkflags}"; local linkcmd="${_ret}"
+
+ local command=""
+ local use_shell_wrapper=false
+ if is_host "msys" "cygwin" "mingw"; then
+ use_shell_wrapper=true
+ command="mkdir -p \"${targetdir}\" && ${linkcmd}"
+ else
+ command="mkdir -p \"${targetdir}\" && ${linkcmd}"
+ fi
+ local description="linking.${_target_mode} ${targetfile}"
+
+ if test_eq "${targetkind}" "shared"; then
+ _get_target_item "${target}" "version"; local version="${_ret}"
+ _get_target_soname "${target}"; local soname="${_ret}"
+ if test_nz "${soname}" && test_nz "${version}"; then
+ _get_target_filename "${target}"; local targetfilename="${_ret}"
+ _get_target_extension "${target}"; local extension="${_ret}"
+ local targetfile_with_version="${targetdir}/${targetfilename}.${version}"
+ if test_eq "${extension}" ".dylib"; then
+ path_basename "${targetfilename}"; local basename="${_ret}"
+ targetfile_with_version="${targetdir}/${basename}.${version}${extension}"
+ fi
+ local targetfile_with_soname="${targetdir}/${soname}"
+ path_filename "${targetfile_with_version}"; local targetfilename_with_version="${_ret}"
+ if test_nq "${soname}" "${targetfilename}" && test_nq "${soname}" "${targetfilename_with_version}"; then
+ command="${command} && cp -p ${targetfile} ${targetfile_with_version} && cd \"${targetdir}\" && ln -sf ${targetfilename_with_version} ${soname} && ln -sf ${soname} ${targetfilename}"
+ fi
+ fi
+ fi
+
+ if ${use_shell_wrapper}; then
+ _shell_escape_single_quotes "${command}"; local command_script="${_ret}"
+ command="sh -lc ${command_script}"
+ fi
+ _ninja_escape "${command}"; command="${_ret}"
+ _ninja_escape "${description}"; description="${_ret}"
+
+ local orderdeps=""
+ local dep=""
+ for dep in ${deps}; do
+ _get_target_file "${dep}"; local depfile="${_ret}"
+ if test_nz "${orderdeps}"; then
+ orderdeps="${orderdeps} ${depfile}"
+ else
+ orderdeps="${depfile}"
+ fi
+ done
+
+ if test_nz "${orderdeps}"; then
+ echo "build ${targetfile}: command ${objectfiles} | ${orderdeps}" >> "${xmake_sh_ninjafile}"
+ else
+ echo "build ${targetfile}: command ${objectfiles}" >> "${xmake_sh_ninjafile}"
+ fi
+ echo " command = ${command}" >> "${xmake_sh_ninjafile}"
+ echo " description = ${description}" >> "${xmake_sh_ninjafile}"
+ echo " restat = 0" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+
+ echo "build ${target}: phony ${targetfile}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+
+ _ninja_add_build_objects "${target}"
+}
+
+_ninja_add_build_targets() {
+ local target=""
+ local defaults=""
+ for target in ${_xmake_sh_targets}; do
+ if _is_target_default "${target}"; then
+ if test_nz "${defaults}"; then
+ defaults="${defaults} ${target}"
+ else
+ defaults="${target}"
+ fi
+ fi
+ done
+ if test_nz "${defaults}"; then
+ echo "build default: phony ${defaults}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+ echo "default default" >> "${xmake_sh_ninjafile}"
+ else
+ echo "default all" >> "${xmake_sh_ninjafile}"
+ fi
+ echo "build all: phony ${_xmake_sh_targets}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+ for target in ${_xmake_sh_targets}; do
+ _ninja_add_build_target "${target}"
+ done
+}
+
+_ninja_add_build() {
+ _ninja_add_build_targets
+}
+
+_ninja_add_run_target() {
+ local target=${1}
+ _get_targetdir "${target}"; local targetdir="${_ret}"
+ _get_target_file "${target}"; local targetfile="${_ret}"
+ local command=""
+ if is_host "msys" "cygwin" "mingw"; then
+ local projectdir="${xmake_sh_projectdir}"
+ local targetfile_rel="./${targetfile}"
+ local targetfile_alt="./build/${targetfile#*/}"
+ local targetbuilddir="${targetfile%/*}"
+ local targetbuilddir_rel="./${targetbuilddir}"
+ local targetbuilddir_alt="./build/${targetbuilddir#*/}"
+ local run_script="cd \"${projectdir}\" && target=\"${targetfile_rel}\"; alt=\"${targetfile_alt}\"; if [ ! -f \"\$target\" ] && [ -f \"\$alt\" ]; then target=\"\$alt\"; fi; if [ ! -f \"\$target\" ]; then echo \"[ninja run] missing ${targetfile_rel} (and fallback ${targetfile_alt})\"; ls -l \"${targetbuilddir_rel}\" || true; ls -l \"${targetbuilddir_alt}\" || true; exit 1; fi; \"\$target\""
+ _shell_escape_single_quotes "${run_script}"; local run_script_escaped="${_ret}"
+ command="sh -lc ${run_script_escaped}"
+ elif is_plat "macosx"; then
+ command="DYLD_LIBRARY_PATH=${targetdir} ${targetfile}"
+ elif is_plat "linux" "bsd"; then
+ command="LD_LIBRARY_PATH=${targetdir} ${targetfile}"
+ else
+ command="${targetfile}"
+ fi
+ local description="running.${_target_mode} ${targetfile}"
+ _ninja_escape "${command}"; command="${_ret}"
+ _ninja_escape "${description}"; description="${_ret}"
+ echo "build run.${target}: command | ${targetfile}" >> "${xmake_sh_ninjafile}"
+ echo " command = ${command}" >> "${xmake_sh_ninjafile}"
+ echo " description = ${description}" >> "${xmake_sh_ninjafile}"
+ echo " restat = 0" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+}
+
+_ninja_add_run_targets() {
+ local target=""
+ local runtargets=""
+ for target in ${_xmake_sh_targets}; do
+ _get_target_item "${target}" "kind"; local kind="${_ret}"
+ if test_eq "${kind}" "binary"; then
+ if _is_target_default "${target}"; then
+ if test_nz "${runtargets}"; then
+ runtargets="${runtargets} run.${target}"
+ else
+ runtargets="run.${target}"
+ fi
+ _ninja_add_run_target "${target}"
+ fi
+ fi
+ done
+ if test_nz "${runtargets}"; then
+ echo "build run: phony ${runtargets}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+ fi
+}
+
+_ninja_add_run() {
+ _ninja_add_run_targets
+}
+
+_ninja_add_clean_target() {
+ local target=${1}
+ _get_target_file "${target}"; local targetfile="${_ret}"
+ _get_target_objectfiles "${target}"; local objectfiles="${_ret}"
+ local removefiles="${targetfile}"
+ local objectfile=""
+ for objectfile in ${objectfiles}; do
+ removefiles="${removefiles} ${objectfile}"
+ done
+
+ _get_targetdir "${target}"; local targetdir="${_ret}"
+ _get_target_item "${target}" "kind"; local targetkind="${_ret}"
+ if test_eq "${targetkind}" "shared"; then
+ _get_target_item "${target}" "version"; local version="${_ret}"
+ _get_target_soname "${target}"; local soname="${_ret}"
+ if test_nz "${soname}" && test_nz "${version}"; then
+ _get_target_filename "${target}"; local filename="${_ret}"
+ _get_target_extension "${target}"; local extension="${_ret}"
+ local targetfile_with_version="${targetdir}/${filename}.${version}"
+ if test_eq "${extension}" ".dylib"; then
+ path_basename "${filename}"; local basename="${_ret}"
+ targetfile_with_version="${targetdir}/${basename}.${version}${extension}"
+ fi
+ local targetfile_with_soname="${targetdir}/${soname}"
+ removefiles="${removefiles} ${targetfile_with_soname} ${targetfile_with_version}"
+ fi
+ fi
+
+ local command="rm -f ${removefiles}"
+ local description="cleaning.${_target_mode} ${target}"
+ _ninja_escape "${command}"; command="${_ret}"
+ _ninja_escape "${description}"; description="${_ret}"
+ echo "build clean.${target}: command" >> "${xmake_sh_ninjafile}"
+ echo " command = ${command}" >> "${xmake_sh_ninjafile}"
+ echo " description = ${description}" >> "${xmake_sh_ninjafile}"
+ echo " restat = 0" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+}
+
+_ninja_add_clean_targets() {
+ local target=""
+ local cleantargets=""
+ for target in ${_xmake_sh_targets}; do
+ if _is_target_default "${target}"; then
+ if test_nz "${cleantargets}"; then
+ cleantargets="${cleantargets} clean.${target}"
+ else
+ cleantargets="clean.${target}"
+ fi
+ _ninja_add_clean_target "${target}"
+ fi
+ done
+ if test_nz "${cleantargets}"; then
+ echo "build clean: phony ${cleantargets}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+ fi
+}
+
+_ninja_add_clean() {
+ _ninja_add_clean_targets
+}
+
+_ninja_install_prepare_script() {
+ local target="${1}"
+ local ninjadir="${xmake_sh_builddir}/.ninja"
+ local scriptdir="${xmake_sh_projectdir}/${ninjadir}"
+ mkdir -p "${scriptdir}"
+ _ret="${scriptdir}/install_${target}.sh"
+ _ret2="${ninjadir}/install_${target}.sh"
+}
+
+_ninja_install_write_header() {
+ local scriptfile="${1}"
+ local escaped_prefix_default="${2}"
+ local escaped_installdir_template="${3}"
+ local escaped_projectdir="${4}"
+ local escaped_bindir_template="${5}"
+ local escaped_libdir_template="${6}"
+ local escaped_includedir_template="${7}"
+
+ cat > "${scriptfile}" <<EOF
+#!/bin/sh
+set -e
+
+prefix=${escaped_prefix_default}
+if [ -n "\${PREFIX}" ]; then
+ prefix="\${PREFIX}"
+fi
+destdir="\${DESTDIR}"
+installdir_template=${escaped_installdir_template}
+placeholder='\${prefix}'
+_rp_value=""
+_rp_replacement=""
+_rp_before=""
+_rp_after=""
+_rp_result=""
+
+replace_placeholder() {
+ _rp_value="\$1"
+ _rp_replacement="\$2"
+ while :; do
+ case "\${_rp_value}" in
+ *\${placeholder}*)
+ _rp_before="\${_rp_value%%\${placeholder}*}"
+ _rp_after="\${_rp_value#*\${placeholder}}"
+ _rp_value="\${_rp_before}\${_rp_replacement}\${_rp_after}"
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+ _rp_result="\${_rp_value}"
+}
+
+projectdir=${escaped_projectdir}
+cd "\${projectdir}"
+
+installdir=""
+if [ -z "\${installdir_template}" ]; then
+ installdir="\${destdir}"
+ if [ -n "\${installdir}" ]; then
+ prefix_trim="\${prefix#/}"
+ installdir="\${installdir}/\${prefix_trim}"
+ else
+ installdir="\${prefix}"
+ fi
+else
+ installdir="\${installdir_template}"
+ replace_placeholder "\${installdir}" "\${prefix}"
+ installdir="\${_rp_result}"
+ if [ -n "\${destdir}" ]; then
+ case "\${installdir}" in
+ /*) ;;
+ *) installdir="\${destdir}/\${installdir}" ;;
+ esac
+ fi
+fi
+
+resolve_prefix_path() {
+ replace_placeholder "\$1" "\${installdir}"
+ printf '%s' "\${_rp_result}"
+}
+
+copy_file() {
+ local src="\$1"
+ local dst_template="\$2"
+ local dst
+ dst=\$(resolve_prefix_path "\${dst_template}")
+ echo "installing \${src} to \${dst}"
+ mkdir -p "\$(dirname "\${dst}")"
+ cp -p "\${src}" "\${dst}"
+}
+
+bindir_template=${escaped_bindir_template}
+libdir_template=${escaped_libdir_template}
+includedir_template=${escaped_includedir_template}
+EOF
+}
+
+_ninja_install_append_target_artifacts() {
+ local scriptfile="${1}"
+ local targetkind="${2}"
+ local install_for_soname="${3}"
+ local targetfile="${4}"
+ local filename="${5}"
+ local version="${6}"
+ local soname="${7}"
+ local extension="${8}"
+ local filename_basename="${9}"
+
+ if test_eq "${targetkind}" "binary"; then
+ _shell_escape_single_quotes "${targetfile}"; local escaped_targetfile="${_ret}"
+ local dest_template="${_install_bindir_default}/${filename}"
+ _shell_escape_single_quotes "${dest_template}"; local escaped_dest_template="${_ret}"
+ echo "copy_file ${escaped_targetfile} ${escaped_dest_template}" >> "${scriptfile}"
+ elif ${install_for_soname}; then
+ local version_template="${_install_libdir_default}/${filename}.${version}"
+ if test_eq "${extension}" ".dylib"; then
+ version_template="${_install_libdir_default}/${filename_basename}.${version}${extension}"
+ fi
+ _shell_escape_single_quotes "${targetfile}"; local escaped_targetfile="${_ret}"
+ _shell_escape_single_quotes "${version_template}"; local escaped_version_template="${_ret}"
+ _shell_escape_single_quotes "${soname}"; local escaped_soname="${_ret}"
+ _shell_escape_single_quotes "${filename}"; local escaped_filename="${_ret}"
+ cat >> "${scriptfile}" <<EOF
+copy_file ${escaped_targetfile} ${escaped_version_template}
+dst_version=\$(resolve_prefix_path ${escaped_version_template})
+dst_dir=\$(dirname "\${dst_version}")
+filename_version=\$(basename "\${dst_version}")
+(
+ cd "\${dst_dir}"
+ ln -sf "\${filename_version}" ${escaped_soname}
+ ln -sf ${escaped_soname} ${escaped_filename}
+)
+EOF
+ elif test_eq "${targetkind}" "static" || test_eq "${targetkind}" "shared"; then
+ _shell_escape_single_quotes "${targetfile}"; local escaped_targetfile="${_ret}"
+ local dest_template="${_install_libdir_default}/${filename}"
+ _shell_escape_single_quotes "${dest_template}"; local escaped_dest_template="${_ret}"
+ echo "copy_file ${escaped_targetfile} ${escaped_dest_template}" >> "${scriptfile}"
+ fi
+}
+
+_ninja_install_append_headerfiles() {
+ local scriptfile="${1}"
+ local headerfiles="${2}"
+ if test_nz "${headerfiles}"; then
+ local srcheaderfile=""
+ for srcheaderfile in ${headerfiles}; do
+ string_split "${srcheaderfile}" ":"
+ local srcheaderpath="${_ret}"
+ local rootdir="${_ret2}"
+ local prefixdir="${_ret3}"
+ local headername="${_ret4}"
+ if test_z "${headername}"; then
+ path_filename "${srcheaderpath}"; headername="${_ret}"
+ fi
+ local dstheaderdir_template="${_install_includedir_default}"
+ if test_nz "${prefixdir}"; then
+ dstheaderdir_template="${dstheaderdir_template}/${prefixdir}"
+ fi
+ local dstheaderfile_template=""
+ if test_nz "${rootdir}"; then
+ path_relative "${rootdir}" "${srcheaderpath}"; local subfile="${_ret}"
+ dstheaderfile_template="${dstheaderdir_template}/${subfile}"
+ else
+ dstheaderfile_template="${dstheaderdir_template}/${headername}"
+ fi
+ _shell_escape_single_quotes "${srcheaderpath}"; local escaped_src="${_ret}"
+ _shell_escape_single_quotes "${dstheaderfile_template}"; local escaped_dst="${_ret}"
+ echo "copy_file ${escaped_src} ${escaped_dst}" >> "${scriptfile}"
+ done
+ fi
+}
+
+_ninja_install_append_installfiles() {
+ local scriptfile="${1}"
+ local installdir="${2}"
+ local installfiles="${3}"
+ if test_nz "${installfiles}"; then
+ local srcinstallfile=""
+ for srcinstallfile in ${installfiles}; do
+ string_split "${srcinstallfile}" ":"
+ local srcfilepath="${_ret}"
+ local rootdir="${_ret2}"
+ local prefixdir="${_ret3}"
+ local installname="${_ret4}"
+ if test_z "${installname}"; then
+ path_filename "${srcfilepath}"; installname="${_ret}"
+ fi
+ local dst_template="${installdir}"
+ if test_z "${dst_template}"; then
+ dst_template="\${prefix}"
+ fi
+ if test_nz "${prefixdir}"; then
+ dst_template="${dst_template}/${prefixdir}"
+ fi
+ if test_nz "${rootdir}"; then
+ path_relative "${rootdir}" "${srcfilepath}"; local subfile="${_ret}"
+ dst_template="${dst_template}/${subfile}"
+ else
+ dst_template="${dst_template}/${installname}"
+ fi
+ _shell_escape_single_quotes "${srcfilepath}"; local escaped_src="${_ret}"
+ _shell_escape_single_quotes "${dst_template}"; local escaped_dst="${_ret}"
+ echo "copy_file ${escaped_src} ${escaped_dst}" >> "${scriptfile}"
+ done
+ fi
+}
+
+_ninja_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}"
+ _get_target_item "${target}" "kind"; local targetkind="${_ret}"
+
+ local install_for_soname=false
+ local version=""
+ local soname=""
+ local extension=""
+ local filename_basename=""
+ if test_eq "${targetkind}" "shared"; then
+ _get_target_item "${target}" "version"; version="${_ret}"
+ _get_target_soname "${target}"; soname="${_ret}"
+ _get_target_extension "${target}"; extension="${_ret}"
+ path_basename "${filename}"; filename_basename="${_ret}"
+ if test_nz "${soname}" && test_nz "${version}"; then
+ local targetfilename_with_version_guess="${filename}.${version}"
+ if test_eq "${extension}" ".dylib"; then
+ targetfilename_with_version_guess="${filename_basename}.${version}${extension}"
+ fi
+ if test_nq "${soname}" "${filename}" && test_nq "${soname}" "${targetfilename_with_version_guess}"; then
+ install_for_soname=true
+ fi
+ fi
+ fi
+
+ _ninja_install_prepare_script "${target}"
+ local scriptfile="${_ret}"
+ local scriptfile_rel="${_ret2}"
+
+ _shell_escape_single_quotes "${_install_prefix_default}"; local escaped_prefix_default="${_ret}"
+ _shell_escape_single_quotes "${installdir}"; local escaped_installdir_template="${_ret}"
+ _shell_escape_single_quotes "${xmake_sh_projectdir}"; local escaped_projectdir="${_ret}"
+ _shell_escape_single_quotes "${_install_bindir_default}"; local escaped_bindir_template="${_ret}"
+ _shell_escape_single_quotes "${_install_libdir_default}"; local escaped_libdir_template="${_ret}"
+ _shell_escape_single_quotes "${_install_includedir_default}"; local escaped_includedir_template="${_ret}"
+
+ _ninja_install_write_header "${scriptfile}" \
+ "${escaped_prefix_default}" \
+ "${escaped_installdir_template}" \
+ "${escaped_projectdir}" \
+ "${escaped_bindir_template}" \
+ "${escaped_libdir_template}" \
+ "${escaped_includedir_template}"
+
+ _ninja_install_append_target_artifacts "${scriptfile}" "${targetkind}" "${install_for_soname}" \
+ "${targetfile}" "${filename}" "${version}" "${soname}" "${extension}" "${filename_basename}"
+
+ _get_target_item "${target}" "headerfiles"; local headerfiles="${_ret}"
+ _ninja_install_append_headerfiles "${scriptfile}" "${headerfiles}"
+
+ _get_target_item "${target}" "installfiles"; local installfiles="${_ret}"
+ _ninja_install_append_installfiles "${scriptfile}" "${installdir}" "${installfiles}"
+
+ echo "" >> "${scriptfile}"
+ chmod +x "${scriptfile}"
+
+ local command="sh ${scriptfile_rel}"
+ local description="installing.${_target_mode} ${target}"
+ _ninja_escape "${command}"; command="${_ret}"
+ _ninja_escape "${description}"; description="${_ret}"
+ echo "build install.${target}: command | ${targetfile}" >> "${xmake_sh_ninjafile}"
+ echo " command = ${command}" >> "${xmake_sh_ninjafile}"
+ echo " description = ${description}" >> "${xmake_sh_ninjafile}"
+ echo " restat = 0" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+}
+
+_ninja_add_install_targets() {
+ local target=""
+ local installtargets=""
+ for target in ${_xmake_sh_targets}; do
+ if _is_target_default "${target}"; then
+ if test_nz "${installtargets}"; then
+ installtargets="${installtargets} install.${target}"
+ else
+ installtargets="install.${target}"
+ fi
+ _ninja_add_install_target "${target}"
+ fi
+ done
+ if test_nz "${installtargets}"; then
+ echo "build install: phony ${installtargets}" >> "${xmake_sh_ninjafile}"
+ echo "" >> "${xmake_sh_ninjafile}"
+ fi
+}
+
+_ninja_add_install() {
+ _ninja_add_install_targets
+}
+
+_ninja_done() {
+ echo "ninja build file is generated!"
+ if "${xmake_sh_diagnosis}"; then
+ cat "${xmake_sh_ninjafile}"
+ fi
+}
+
# generate build file for ninja
_generate_for_ninja() {
- raise "Ninja generator has been not supported!"
+ _ninja_begin
+ _ninja_add_header
+ _ninja_add_switches
+ _ninja_add_toolchains
+ _ninja_add_flags
+ _ninja_add_rules
+ _ninja_add_build
+ _ninja_add_clean
+ _ninja_add_install
+ _ninja_add_run
+ _ninja_done
}
#-----------------------------------------------------------------------------