Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #! /usr/bin/env bash
- set -e -u
- throwError () { local error_keyword="${1}" ; local error_message="${2}"
- local error_code
- case "${error_keyword}" in
- 'BADREQUEST') error_code=2 ;;
- 'INTERNAL') error_code=3 ;;
- 'NOTIMPLEMENTED') error_code=4 ;;
- esac
- printf 'ERROR %s: %s\n' "${error_keyword}" "${error_message}" >&2
- exit "${error_code}"
- }
- printHelp () {
- local prog_name="$(basename "${0}")"
- sed -e 's|\\t|\t|g;s|\\n|\n|g' <<-EOF
- ${prog_name}: a tool to build game for release purpose.\n
- Usage:\n
- \t${prog_name} [option] <target>\n
- The script must be called within game source directory,
- but can be called from everywhere in source directory.\n
- Option can be:\n
- \t-j<NUMBER>
- \t\twith NUMBER the number of parallel compilation jobs\n
- \t-p
- \t\tbuild multiple targets at once in parallel
- \t\tbeware: return code will be inaccurate\n
- \t-v
- \t\twrite package version strings\n
- Target can be:\n
- \tvm
- \t\tbuild virtual machine\n
- \tlinux-i686
- \t\tbuild linux x86 engine\n
- \tlinux-amd64
- \t\tbuild linux x86_64 engine\n
- \tmacos-amd64
- \t\tbuild mac x86_64 engine\n
- \twindows-i686
- \t\tbuild windows x86 engine\n
- \twindows-amd64
- \t\tbuild windows x86_64 engine\n
- Example:\n
- \t${prog_name} vm linux-amd64\n
- EOF
- exit
- }
- getUserName () {
- whoami | tr '[:upper:]' '[:lower:]' | tr -d '[:blank:]' | tr -d '[:punct:]' | cut -c'1-10'
- }
- getBinPath () { local system_windows="${1}" ; local bin_name="${2}"
- if "${system_windows}" ; then
- echo "${bin_name}.exe"
- else
- echo "${bin_name}"
- fi
- }
- dumpSymbols () { local dumpsyms_bin="${1}" ; local symbol_dir="${2}" ; local exec_file="${3}"
- local temp_file="$(mktemp)"
- "${dumpsyms_bin}" "${exec_file}" > "${temp_file}"
- local symbol_basename="$(head -n'1' "${temp_file}" | cut -f'5' -d' ')"
- local build_id="$(head -n'1' "${temp_file}" | cut -f'4' -d' ')"
- local exec_symbol_dir="${symbol_dir}/${symbol_basename}/${build_id}"
- mkdir -pv "${exec_symbol_dir}"
- mv "${temp_file}" "${exec_symbol_dir}/${symbol_basename}.sym"
- }
- findDll () { local mingw_arch="${1}" local dll_name="${2}"
- if [ -z "${mingw_arch}" ]; then
- find "${MINGW_PREFIX}/bin/${dll_name}"
- return
- fi
- find '/usr' -name "${dll_name}" -type f | sort | grep --max-count=1 "${mingw_arch}" || throwError INTERNAL "couldn't find DLL ${dll_name}"
- }
- cleanSymbols () { local symbol_dir="${1}" ; local symbol_archive_filename="${2}"
- if [ -e "${symbol_dir}" ] ; then
- find "${symbol_dir}" -type f -name '*.sym' -exec rm -v {} \;
- find "${symbol_dir}" -depth -type d -exec rmdir {} \;
- fi
- if [ -f "${symbol_archive_filename}" ] ; then
- rm "${symbol_archive_filename}"
- fi
- }
- cleanEngineBuildDir () { local content_dir="${1}"
- if [ -e "${content_dir}" ] ; then
- find "${content_dir}" -type f -exec rm -v {} \;
- find "${content_dir}" -depth -type d -exec rmdir {} \;
- fi
- }
- cleanVmBuildDir () { local content_dir="${1}" ; local symbol_archive_basename="${2}"
- if [ -e "${content_dir}" ] ; then
- find "${content_dir}" -type f -name '?game-*.nexe' -exec rm -v {} \;
- find "${content_dir}" -type f -name "${symbol_archive_basename}.*" -exec rm -v {} \;
- find "${content_dir}" -depth -type d -exec rmdir {} \;
- fi
- }
- package () { local archive_format="${1}" ; local archive_filename="${2}" ; local content_dir="${3}"
- ( cd "${content_dir}"
- [ -f "${archive_filename}" ] && rm -v "${archive_filename}"
- 7z -mx='9' -t"${archive_format}" a "${archive_filename}" .
- )
- }
- build () { local job_count="${1}" ; local write_version_string="${2}" ; local root_dir="${3}" ; local target="${4}"
- local symbol_archive_basename='symbols'
- local vmpak_archive_basename=''
- local engine_archive_basename=''
- local engine_archive_format='zip'
- local symbol_archive_format='7z'
- local vmpak_archive_format='zip'
- local vmpak_archive_extension='dpk'
- local build_dir="${root_dir}/build"
- local release_dir="${build_dir}/release"
- local vm_kind_list='cgame sgame'
- local vm_arch_list='x86 x86_64'
- local main_nexe='main.nexe'
- local engine_file_list=''
- local engine_strip_list=''
- local engine_symbolize_list=''
- local build_vm='false'
- local build_engine='false'
- local system_linux='false'
- local system_macos='false'
- local system_windows='false'
- local dumpsyms_relpath=''
- local arch_amd64='false'
- local arch_i686='false'
- local host_linux='false'
- local host_mac='false'
- local host_windows='false'
- local mingw_arch_prefix=''
- case "${target}" in
- 'vm') build_vm='true'
- dumpsyms_relpath=linux/dump_syms/dump_syms ;;
- 'linux-'*) build_engine='true' ; system_linux='true'
- dumpsyms_relpath=linux/dump_syms/dump_syms ;;
- 'macos-'*) build_engine='true' ; system_macos='true'
- dumpsyms_relpath=mac/dump_syms/dump_syms_mac ;;
- 'windows-'*) build_engine='true' ; system_windows='true'
- dumpsyms_relpath=windows/dump_syms_dwarf/dump_syms ;;
- esac
- case "${target}" in
- *'-amd64')
- arch_amd64='true'
- engine_file_list="${engine_file_list} irt_core-x86_64.nexe" ;;
- *'-i686')
- arch_i686='true'
- engine_file_list="${engine_file_list} irt_core-x86.nexe" ;;
- esac
- local target_root_dir="${build_dir}/target"
- local target_build_dir="${target_root_dir}/${target}"
- local content_dir="${target_build_dir}/content"
- local symbol_dir="${target_build_dir}/${symbol_archive_basename}"
- local symbol_archive_filename="${target_build_dir}/${symbol_archive_basename}.${symbol_archive_format}"
- local uname_system="$(uname -s)"
- case "${uname_system}" in
- 'Linux'*) host_linux='true' ;;
- 'Darwin'*) host_mac='true' ;;
- 'CYGWIN'*|'MINGW'*) host_windows='true' ;;
- *) throwError NOTIMPLEMENTED "unknown system: ${uname_system}" ;;
- esac
- if "${write_version_string}" ; then
- git_last_commit="$(git rev-list HEAD | head -n 1)"
- git_last_commit_short="$(git rev-list HEAD | head -n 1 | cut -c1-7)"
- git_ref="$(git describe --tags --match 'v*' | cut -c2-)"
- git_last_tag="$(git describe --tags --match 'v*' | cut -f1 -d'-' | cut -c2-)"
- git_last_date="$(date --date="@$(git log -1 '--pretty=format:%ct')" -u '+%Y%m%d-%H%M%S')"
- if [ "${git_ref}" = "${git_last_tag}" ] ; then
- build_version="${git_ref}"
- else
- build_version="${git_last_tag}+${git_last_date}+${git_last_commit_short}+$(getUserName)"
- fi
- vmpak_version_string="_${build_version}"
- engine_version_string="_${build_version}"
- else
- vmpak_version_string='_0'
- engine_version_string=''
- fi
- if [ -z "${job_count}" ] ; then
- if command -v 'nproc' >/dev/null ; then
- job_count="$(nproc)"
- elif command -v 'sysctl' >/dev/null ; then
- job_count="$(sysctl -n 'hw.ncpu')"
- else
- job_count='4'
- fi
- fi
- if [ -d "${target_build_dir}" ] ; then
- echo "Removing '${target_build_dir}' and contents"
- rm -r "${target_build_dir}"
- fi
- mkdir -pv "${target_build_dir}"
- mkdir -pv "${release_dir}"
- local cmake_opts='-DBUILD_GAME_NATIVE_DLL=OFF -DBUILD_GAME_NATIVE_EXE=OFF'
- local cmake_cflags=''
- if "${system_macos}" ; then
- PATH="${PATH}:/Applications/CMake.app/Contents/bin"
- cmake_opts="${cmake_opts} -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 -DCMAKE_BUILD_TYPE=Release -DUSE_BREAKPAD=OFF -DGMP_LIBRARY=${target_build_dir}/external_deps/macosx64-5/lib/libgmp.a"
- produce_symbols=false
- else
- cmake_opts="${cmake_opts} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_BREAKPAD=ON"
- produce_symbols=true
- fi
- if "${system_macos}" && "${arch_amd64}" ; then
- cmake_opts="${cmake_opts} -DCMAKE_OSX_ARCHITECTURES=x86_64"
- fi
- if "${build_vm}" ; then
- vmpak_archive_basename='vm'
- cmake_opts="${cmake_opts} -DBUILD_GAME_NACL=ON -DBUILD_GAME_NACL_NEXE=ON -DBUILD_CGAME=ON -DBUILD_SGAME=ON -DBUILD_CLIENT=OFF -DBUILD_TTY_CLIENT=OFF -DBUILD_SERVER=OFF"
- fi
- if "${build_engine}" ; then
- engine_archive_basename="${target}"
- cmake_opts="${cmake_opts} -DUSE_LTO=ON -DBUILD_CLIENT=ON -DBUILD_SERVER=ON -DBUILD_TTY_CLIENT=ON -DBUILD_GAME_NACL=OFF -DBUILD_GAME_NACL_NEXE=OFF -DBUILD_CGAME=OFF -DBUILD_SGAME=OFF -DUSE_HARDENING=1"
- local strip='strip'
- if "${system_windows}" && ! "${host_windows}" ; then
- if "${arch_i686}" ; then
- bitness='32' ; mingw_arch_prefix='i686'
- else
- bitness='64' ; mingw_arch_prefix='x86_64'
- fi
- strip="${mingw_arch_prefix}-w64-mingw32-strip"
- cmake_opts="${cmake_opts} -DCMAKE_TOOLCHAIN_FILE=${root_dir}/daemon/cmake/cross-toolchain-mingw${bitness}.cmake"
- fi
- if ${system_linux} ; then
- cmake_opts="${cmake_opts} -DUSE_STATIC_LIBS=1 -DOpenGL_GL_PREFERENCE=LEGACY"
- engine_file_list="${engine_file_list} daemon daemonded daemon-tty crash_server nacl_helper_bootstrap nacl_loader"
- engine_symbolize_list='daemon daemonded daemon-tty'
- engine_strip_list='daemon daemonded daemon-tty crash_server'
- if "${arch_i686}" ; then
- cmake_opts="${cmake_opts} -DCMAKE_TOOLCHAIN_FILE=${root_dir}/daemon/cmake/cross-toolchain-linux32.cmake"
- fi
- fi
- if "${system_macos}" ; then
- engine_file_list="${engine_file_list} daemon daemonded daemon-tty nacl_loader libGLEW.2.2.0.dylib libopenal.1.18.2.dylib"
- fi
- if "${system_windows}" ; then
- if "${arch_i686}" ; then
- if "${host_windows}" ; then
- special_dll='libgcc_s_dw2-1.dll'
- else
- special_dll='libgcc_s_sjlj-1.dll'
- fi
- else
- special_dll='libgcc_s_seh-1.dll'
- fi
- extra_dll_list="${special_dll} libstdc++-6.dll libwinpthread-1.dll libssp-0.dll"
- engine_file_list="${engine_file_list} daemon.exe daemonded.exe daemon-tty.exe crash_server.exe nacl_loader.exe"
- engine_symbolize_list='daemon.exe daemonded.exe daemon-tty.exe'
- engine_strip_list='daemon.exe daemonded.exe daemon-tty.exe crash_server.exe'
- for dll_name in ${extra_dll_list} ; do
- dll_location="$(findDll "${mingw_arch_prefix}" "${dll_name}")"
- cp -av "${dll_location}" "${target_build_dir}/"
- done
- fi
- local strip='strip'
- if "${system_windows}" && ! "${host_windows}" ; then
- if "${arch_i686}" ; then
- bitness='32' ; mingw_arch_prefix='i686'
- else
- bitness='64' ; mingw_arch_prefix='x86_64'
- fi
- strip="${mingw_arch_prefix}-w64-mingw32-strip"
- cmake_opts="${cmake_opts} -DCMAKE_TOOLCHAIN_FILE=${root_dir}/daemon/cmake/cross-toolchain-mingw${bitness}.cmake"
- fi
- fi
- if "${build_vm}" ; then
- cmake -H"${root_dir}" -B"${target_build_dir}" -G"Unix Makefiles" ${cmake_opts} || throwError INTERNAL "${target} cmake failed"
- fi
- if "${build_engine}" ; then
- cmake -H"${root_dir}" -B"${target_build_dir}" -G"Unix Makefiles" -D"CMAKE_C_FLAGS=${cmake_cflags}" -D"CMAKE_CXX_FLAGS=${cmake_cflags}" -D"CMAKE_EXE_LINKER_FLAGS=${cmake_cflags}" ${cmake_opts} || throwError INTERNAL "${target} cmake failed"
- fi
- if "${build_vm}" || "${build_engine}" ; then
- daemon_dir="$(cmake -H"${root_dir}" -B"${target_build_dir}" -LH | grep '^DAEMON_DIR:' | sed -e 's/[^=]*=//')"
- fi
- if "${system_macos}" ; then
- mkdir -v "${target_build_dir}/external_deps"
- ( cd "${target_build_dir}/external_deps"
- "${daemon_dir}/external_deps/build.sh" macosx64 gmp
- "${daemon_dir}/external_deps/build.sh" macosx64 install
- )
- fi
- if "${build_vm}" ; then
- cmake --build "${target_build_dir}" -- -j"${job_count}" nacl-vms || throwError INTERNAL "${target} build failed"
- fi
- if "${build_engine}" ; then
- cmake --build "${target_build_dir}" -- -j"${job_count}" || throwError INTERNAL "${target} build failed"
- if "${system_windows}" ; then
- engine_file_list="${engine_file_list} $(cd "${target_build_dir}" && ls *.dll)"
- fi
- fi
- if "${produce_symbols}" ; then
- local breakpad_dir="${daemon_dir}/libs/breakpad"
- local dumpsyms_bin="$(getBinPath ${host_windows} ${breakpad_dir}/src/tools/${dumpsyms_relpath})"
- if ! [ -d "${breakpad_dir}" ] ; then
- throwError INTERNAL "breakpad dir missing: ${breakpad_dir}"
- fi
- set +e
- "${dumpsyms_bin}" --help 2>/dev/null
- local exitcode=$?
- set -e
- if [ "${exitcode}" -gt 1 ] ; then
- ( cd "${breakpad_dir}"
- autoreconf -fvi && ./configure || throwError INTERNAL 'breakpad configure failed'
- )
- make -C"${breakpad_dir}" clean || true
- local make_targets=''
- if "${host_windows}" ; then
- make_targets='src/tools/windows/dump_syms_dwarf/dump_syms.exe'
- fi
- make -j"${job_count}" -C"${breakpad_dir}" $make_targets || throwError INTERNAL 'breakpad build failed'
- fi
- fi
- if "${build_vm}" ; then
- cleanSymbols "${symbol_dir}" "${symbol_archive_filename}"
- for vm in ${vm_kind_list} ; do
- for arch in ${vm_arch_list} ; do
- ( cd "${target_build_dir}"
- local vm_file="${vm}-${arch}.nexe"
- local stripped_vm_file="${vm}-${arch}-stripped.nexe"
- printf 'extracting symbols from %s\n' "${vm_file}"
- if ! [ -f "${vm_file}" ] ; then
- throwError INTERNAL "missing: ${vm_file}"
- fi
- if [ -f "${main_nexe}" ] ; then
- rm "${main_nexe}"
- fi
- ln -s "${vm_file}" 'main.nexe'
- dumpSymbols "${dumpsyms_bin}" "${symbol_dir}" "${main_nexe}"
- mkdir -pv "${content_dir}"
- cp -v "${stripped_vm_file}" "${content_dir}/${vm_file}"
- )
- done
- done
- package "${symbol_archive_format}" "${symbol_archive_filename}" "${symbol_dir}"
- cp -v "${symbol_archive_filename}" "${content_dir}/${symbol_archive_basename}.${symbol_archive_format}"
- vmpak_archive_filename="${release_dir}/${vmpak_archive_basename}${vmpak_version_string}.${vmpak_archive_extension}"
- if [ -f "${vmpak_archive_filename}" ] ; then
- rm -v "${vmpak_archive_filename}"
- fi
- package "${vmpak_archive_format}" "${vmpak_archive_filename}" "${content_dir}"
- cleanSymbols "${symbol_dir}" "${symbol_archive_filename}"
- cleanVmBuildDir "${content_dir}" "${symbol_archive_basename}"
- fi
- if "${build_engine}" ; then
- cleanSymbols "${symbol_dir}" "${symbol_archive_filename}"
- mkdir -pv "${content_dir}"
- if "${produce_symbols}" ; then
- for bin in ${engine_symbolize_list} ; do
- local bin_path="${target_build_dir}/${bin}"
- printf 'extracting symbols from %s\n' "${bin_path}"
- dumpSymbols "${dumpsyms_bin}" "${symbol_dir}" "${bin_path}"
- done
- fi
- local engine_file_dest="${content_dir}"
- if "${system_macos}" ; then
- engine_file_dest="${content_dir}/Unvanquished.app/Contents/MacOS"
- mkdir -pv "${engine_file_dest}"
- cp -v "${root_dir}/macosx/unvanquished.sh" "${engine_file_dest}"
- cp -av "${target_build_dir}/SDL2.framework" "${engine_file_dest}"
- rm -rv "${engine_file_dest}/SDL2.framework/Headers"
- rm -rv "${engine_file_dest}/SDL2.framework/Versions/A/Headers"
- rm -rv "${engine_file_dest}/SDL2.framework/Versions/Current/Headers"
- cp -v "${root_dir}/macosx/Info.plist" "${content_dir}/Unvanquished.app/Contents"
- mkdir -v "${content_dir}/Unvanquished.app/Contents/Resources"
- cp -v "${root_dir}/macosx/Unvanquished.icns" "${content_dir}/Unvanquished.app/Contents/Resources"
- fi
- for file in ${engine_file_list} ; do
- cp -v "${target_build_dir}/${file}" "${engine_file_dest}/${file}"
- done
- for file in ${engine_strip_list} ; do
- echo "Stripping ${file}"
- "${strip}" "${engine_file_dest}/${file}"
- done
- if "${produce_symbols}" ; then
- package "${symbol_archive_format}" "${symbol_archive_filename}" "${symbol_dir}"
- cp -v "${symbol_archive_filename}" "${content_dir}/${symbol_archive_basename}-${target}.${symbol_archive_format}"
- fi
- engine_archive_filename="${release_dir}/${engine_archive_basename}${engine_version_string}.${engine_archive_format}"
- if [ -f "${engine_archive_filename}" ] ; then
- rm -v "${engine_archive_filename}"
- fi
- package "${engine_archive_format}" "${engine_archive_filename}" "${content_dir}"
- cleanSymbols "${symbol_dir}" "${symbol_archive_filename}"
- cleanEngineBuildDir "${content_dir}"
- fi
- }
- root_dir="$(git rev-parse --show-toplevel)"
- [ -f "${root_dir}/src/cgame/cg_main.cpp" ] || throwError INTERNAL "must be called from game source tree"
- [ -z "${1:-}" ] && throwError BADREQUEST 'missing target'
- job_count=''
- parallel_target='false'
- write_version_string='false'
- target_list=''
- while [ -n "${1:-}" ] ; do
- case "${1}" in
- 'vm'|'linux-amd64'|'linux-i686'|'macos-amd64'|'windows-amd64'|'windows-i686')
- target_list="${target_list} ${1}" ; shift ;;
- 'macos-i686') throwError NOTIMPLEMENTED "unsupported target: ${1}" ;;
- '-d') set -x ; shift ;;
- '-j'*) job_count="${1:2}" ; shift ;;
- '-p') parallel_target='true' ; shift ;;
- '-v') write_version_string='true' ; shift ;;
- '-h'|'--help') printHelp ;;
- '-'*) throwError BADREQUEST "unknown option: ${1}" ;;
- *) throwError BADREQUEST "unknown target: ${1}" ;;
- esac
- done
- for target in ${target_list} ; do
- if "${parallel_target}" ; then
- build "${job_count}" "${write_version_string}" "${root_dir}" "${target}" &
- else
- build "${job_count}" "${write_version_string}" "${root_dir}" "${target}"
- fi
- done ; wait
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement