diff options
| author | ruki <[email protected]> | 2025-11-13 00:44:11 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-11-13 00:44:11 +0800 |
| commit | d265e8c94bde4cdc5bdb1f6bc268a8ccd79ab964 (patch) | |
| tree | 166a4bc484ce6415a22d1128a0a99d2c23102e03 | |
| parent | d4205f6eca2257d69db51089341490e369552180 (diff) | |
update xmake.sh
| -rwxr-xr-x | configure | 785 |
1 files changed, 754 insertions, 31 deletions
@@ -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 } #----------------------------------------------------------------------------- |
