Compare commits
	
		
			42 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| fc13836423 | |||
| f69b0a4214 | |||
| 0ba79fd489 | |||
| e16284f3aa | |||
| 09e54a670a | |||
| 9827395c8c | |||
| ef272847e1 | |||
| 2271d6bde1 | |||
| 32a254468b | |||
| 50dbda6ccc | |||
| 3fff3b487b | |||
| 297937aeb3 | |||
| ca9a116e9b | |||
| ca637f057b | |||
| d366c94ac8 | |||
| ce379beeb2 | |||
| 2d4dffe38f | |||
| 124ef802b3 | |||
| ad326019fd | |||
| 079af46983 | |||
| 17fb344798 | |||
| d5595e2a7f | |||
| 317fedec34 | |||
| 703df71191 | |||
| 4f66ebfd88 | |||
| ba0a50682f | |||
| 3b394fc175 | |||
| 97491fb72a | |||
| ef1065278b | |||
| 391a58dffc | |||
| bd4b7763d4 | |||
| 33ce9e38d2 | |||
| 409aa4ffb4 | |||
| b951abd511 | |||
| 2171eaeed6 | |||
| 7075a9ad58 | |||
| 9025a85bcc | |||
| 3342b87fd0 | |||
| cd4b20b701 | |||
| fc120f4f33 | |||
| b8d5a76ee7 | |||
| 009d4a3421 | 
							
								
								
									
										17
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -3,18 +3,27 @@ run-name: ${{ github.actor }} runs Gitea Actions | |||||||
| on: [push] | on: [push] | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   XTChain: |   XTchain: | ||||||
|  |     strategy: | ||||||
|  |       matrix: | ||||||
|  |         target: [linux, windows] | ||||||
|  |         build: [full, minimal] | ||||||
|     runs-on: oscw |     runs-on: oscw | ||||||
|     container: |     container: | ||||||
|       image: codingworkshop/oscw-runner:latest |       image: codingworkshop/oscw-runner:latest | ||||||
|     steps: |     steps: | ||||||
|       - name: Clone repository |       - name: Clone repository | ||||||
|         uses: actions/checkout@v3 |         uses: actions/checkout@v3 | ||||||
|       - name: Build XTChain |       - name: Build XTchain | ||||||
|         run: CORES=10 ./build-linux.sh |         run: | | ||||||
|  |           if [ "${{ matrix.build }}" == "minimal" ]; then | ||||||
|  |             ./build.sh --jobs=10 --target=${{ matrix.target }} --minimal | ||||||
|  |           else | ||||||
|  |             ./build.sh --jobs=10 --target=${{ matrix.target }} | ||||||
|  |           fi | ||||||
|       - name: Publish binaries |       - name: Publish binaries | ||||||
|         if: startsWith(github.ref, 'refs/tags/') |         if: startsWith(github.ref, 'refs/tags/') | ||||||
|         env: |         env: | ||||||
|           OSCW_GITHUB_USERNAME: ${{ secrets.OSCW_GITHUB_USERNAME }} |           OSCW_GITHUB_USERNAME: ${{ secrets.OSCW_GITHUB_USERNAME }} | ||||||
|           OSCW_GITHUB_PASSWORD: ${{ secrets.OSCW_GITHUB_PASSWORD }} |           OSCW_GITHUB_PASSWORD: ${{ secrets.OSCW_GITHUB_PASSWORD }} | ||||||
|         run: github_publish $OSCW_GITHUB_USERNAME $OSCW_GITHUB_PASSWORD $(ls xtchain-*-linux.tar.zst) |         run: github_publish $OSCW_GITHUB_USERNAME $OSCW_GITHUB_PASSWORD $(ls xtchain-*-${{ matrix.target }}.*) | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								README.md
									
									
									
									
									
								
							| @@ -14,39 +14,36 @@ | |||||||
|   <a href="https://github.com/sponsors/xt-sys/"> |   <a href="https://github.com/sponsors/xt-sys/"> | ||||||
|     <img alt="Sponsors" src="https://img.shields.io/badge/Sponsor-%E2%9D%A4-red?logo=GitHub"> |     <img alt="Sponsors" src="https://img.shields.io/badge/Sponsor-%E2%9D%A4-red?logo=GitHub"> | ||||||
|   </a> |   </a> | ||||||
|   <a href="https://discord.com/invite/3zgjQDVmAe"> |   <a href="https://discord.com/invite/zBzJ5qMGX7"> | ||||||
|     <img alt="Discord" src="https://img.shields.io/discord/723186294540206100?label=Chat"> |     <img alt="Discord" src="https://img.shields.io/badge/Chat-Join%20Discord-success"> | ||||||
|   </a> |   </a> | ||||||
| </p> | </p> | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
| ## XT Toolchain | ## XT Toolchain | ||||||
| This is a LLVM/Clang/LLD based mingw-w64 toolchain. It currently supports C and C++, and provides | The XT Toolchain is a build environment based on LLVM/Clang/LLD. It currently supports C and C++, and includes | ||||||
| a variety of tools including IDL, message and resource compilers. The XT Toolchain is also the | a variety of auxiliary tools such as IDL, message, and resource compilers. The XT Toolchain is the official | ||||||
| official build environment for compiling XT software, including the XT OS. Currently, it is | build system for compiling XT software, including the XT OS. It is currently available for Linux and Windows | ||||||
| targeted at Linux host only, however it should be possible to build it in MSYS2 as well. | host systems. | ||||||
|  |  | ||||||
| Benefits of a LLVM based MinGW toolchain are: | Key Benefits of using an LLVM-based Toolchain: | ||||||
|  * Single toolchain targeting all architectures (i686, x86_64, armv7 and aarch64), |  * Unified toolchain for multiple target architectures: i686, x86_64, armv7, and aarch64 | ||||||
|  * Support for generating debug info in PDB format, |  * Support for generating debug information in PDB format | ||||||
|  * Support for targeting ARM/AARCH64 architectures and ability to produce Windows ARM binaries. |  * Ability to target ARM/AArch64 architectures and produce ARM binaries | ||||||
|  |  | ||||||
| This software includes: | This toolchain includes the following software: | ||||||
|  * CMake |  * CMake | ||||||
|  * GNU Assembler |  | ||||||
|  * LLVM |  * LLVM | ||||||
|  * Make |  | ||||||
|  * Mingw-w64 |  | ||||||
|  * Ninja |  * Ninja | ||||||
|  * Wine |  * Wine | ||||||
|  |  | ||||||
| This software is based on [LLVM MinGW Toolchain](https://github.com/mstorsjo/llvm-mingw). | **Note:** This toolchain is based on the [LLVM MinGW Toolchain](https://github.com/mstorsjo/llvm-mingw). | ||||||
|  |  | ||||||
| ## Licensing | ## Licensing | ||||||
| The XTchain project includes the scripts for building and assembling a toolchain as well as wrappers | The XTchain project includes scripts for building and assembling the toolchain, as well as the environment | ||||||
| for LLVM tools and environmental shell. These are licensed under the GPLv3 license. It covers only | shell. These components are licensed under the GNU GPLv3 license. This license applies only to the parts | ||||||
| mentioned components that are provided by XTchain directly. For more information on that, refer to | provided directly by XTchain. For detailed information, please refer to the COPYING.md file. | ||||||
| the COPYING.md file. The final pre-built toolchain is covered by the licenses of the individual, |  | ||||||
| external projects. The full list of software incorporated into this toolchain is available in the | The final pre-built toolchain is subject to the licenses of the individual third-party projects it includes. | ||||||
| README.md file. | A complete list of the external software used in this toolchain can be found in the README.md file. | ||||||
|   | |||||||
							
								
								
									
										621
									
								
								build-linux.sh
									
									
									
									
									
								
							
							
						
						
									
										621
									
								
								build-linux.sh
									
									
									
									
									
								
							| @@ -1,621 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
| # PROJECT:     XTchain |  | ||||||
| # LICENSE:     See the COPYING.md in the top level directory |  | ||||||
| # FILE:        build-linux.sh |  | ||||||
| # DESCRIPTION: Toolchain building and assembly script |  | ||||||
| # DEVELOPERS:  Rafal Kupiec <belliash@codingworkshop.eu.org> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Working Directories |  | ||||||
| BINDIR="$(pwd)/binaries" |  | ||||||
| PCHDIR="$(pwd)/patches" |  | ||||||
| SRCDIR="$(pwd)/sources" |  | ||||||
| WRKDIR="$(pwd)" |  | ||||||
|  |  | ||||||
| # Architecture Settings |  | ||||||
| ARCHS="aarch64 armv7 i686 x86_64" |  | ||||||
| GENERIC="generic-w64-mingw32" |  | ||||||
|  |  | ||||||
| # Binutils Settings |  | ||||||
| BINUTILSDIR="${SRCDIR}/binutils" |  | ||||||
| BINUTILSTAG="binutils-2_41" |  | ||||||
| BINUTILSVCS="git://sourceware.org/git/binutils-gdb.git" |  | ||||||
|  |  | ||||||
| # CMake Settings |  | ||||||
| CMAKEDIR="${SRCDIR}/cmake" |  | ||||||
| CMAKETAG="v3.27.6" |  | ||||||
| CMAKEVCS="https://gitlab.kitware.com/cmake/cmake.git" |  | ||||||
|  |  | ||||||
| # LLVM Settings |  | ||||||
| LLVMDIR="${SRCDIR}/llvm" |  | ||||||
| LLVMTAG="llvmorg-17.0.6" |  | ||||||
| LLVMVCS="https://github.com/llvm/llvm-project.git" |  | ||||||
|  |  | ||||||
| # Make Settings |  | ||||||
| MAKEDIR="${SRCDIR}/make" |  | ||||||
| MAKETAG="4.4.1" |  | ||||||
| MAKEVCS="git://git.savannah.gnu.org/make" |  | ||||||
|  |  | ||||||
| # Mingw-w64 Settings |  | ||||||
| MINGWDIR="${SRCDIR}/mingw-w64" |  | ||||||
| MINGWLIB="ucrt" |  | ||||||
| MINGWTAG="master" |  | ||||||
| MINGWNTV="0x601" |  | ||||||
| MINGWVCS="https://github.com/mirror/mingw-w64.git" |  | ||||||
|  |  | ||||||
| # Ninja Settings |  | ||||||
| NINJADIR="${SRCDIR}/ninja" |  | ||||||
| NINJATAG="v1.11.1" |  | ||||||
| NINJAVCS="https://github.com/ninja-build/ninja.git" |  | ||||||
|  |  | ||||||
| # Wine Settings |  | ||||||
| WINEDIR="${SRCDIR}/wine" |  | ||||||
| WINETAG="wine-8.17" |  | ||||||
| WINEVCS="git://source.winehq.org/git/wine.git" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # This function applies a patches to the 3rd party project |  | ||||||
| apply_patches() |  | ||||||
| { |  | ||||||
|     local PACKAGE="${1}" |  | ||||||
|     local VERSION="${2}" |  | ||||||
|     if [ -d "${PCHDIR}/${PACKAGE}/${VERSION}" ]; then |  | ||||||
|         PATCHES="$(find ${PCHDIR}/${PACKAGE}/${VERSION} -name '*.diff' -o -name '*.patch' | sort -n)" |  | ||||||
|         echo ">>> Applying custom patches ..." |  | ||||||
|         for PATCH in ${PATCHES}; do |  | ||||||
|             if [ -f "${PATCH}" ] && [ -r "${PATCH}" ]; then |  | ||||||
|                 for PREFIX in {0..5}; do |  | ||||||
|                     if patch -i${PATCH} -p${PREFIX} --silent --dry-run >/dev/null; then |  | ||||||
|                         patch -i${PATCH} -p${PREFIX} --silent |  | ||||||
|                         echo ">>> Patch ${PATCH} applied ..." |  | ||||||
|                         break; |  | ||||||
|                     elif [ ${PREFIX} -ge 5 ]; then |  | ||||||
|                         echo "Patch ${PATCH} does not fit. Failed applying patch ..." |  | ||||||
|                         return 1 |  | ||||||
|                     fi |  | ||||||
|                 done |  | ||||||
|             fi |  | ||||||
|         done |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and installs GNU BINUTILS |  | ||||||
| binutils_build() |  | ||||||
| { |  | ||||||
|     echo ">>> Building BINUTILS ..." |  | ||||||
|     for ARCH in ${ARCHS}; do |  | ||||||
|         [ -z ${CLEAN} ] || rm -rf ${BINUTILSDIR}/build-${ARCH} |  | ||||||
|         mkdir -p ${BINUTILSDIR}/build-${ARCH} |  | ||||||
|         cd ${BINUTILSDIR}/build-${ARCH} |  | ||||||
|         case ${ARCH} in |  | ||||||
|             "armv7") |  | ||||||
|                 TARGET="arm" |  | ||||||
|                 ;; |  | ||||||
|             *) |  | ||||||
|                 TARGET="${ARCH}" |  | ||||||
|                 ;; |  | ||||||
|         esac |  | ||||||
|         ../configure \ |  | ||||||
|             --target=${TARGET}-w64-mingw32 \ |  | ||||||
|             --disable-binutils \ |  | ||||||
|             --disable-gdb \ |  | ||||||
|             --disable-gprof \ |  | ||||||
|             --disable-ld \ |  | ||||||
|             --disable-multilib \ |  | ||||||
|             --disable-nls \ |  | ||||||
|             --disable-werror \ |  | ||||||
|             --with-zlib=yes |  | ||||||
|         make -j${CORES} |  | ||||||
|         cp ${BINUTILSDIR}/build-${ARCH}/gas/as-new ${BINDIR}/bin/${ARCH}-w64-mingw32-gas |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function downloads GNU BINUTILS from VCS |  | ||||||
| binutils_fetch() |  | ||||||
| { |  | ||||||
|     if [ ! -d ${BINUTILSDIR} ]; then |  | ||||||
|         echo ">>> Downloading BINUTILS ..." |  | ||||||
|         git clone --depth 1 --branch ${BINUTILSTAG} ${BINUTILSVCS} ${BINUTILSDIR} |  | ||||||
|         cd ${BINUTILSDIR} |  | ||||||
|         apply_patches ${BINUTILSDIR##*/} ${BINUTILSTAG##*-} |  | ||||||
|         cd ${WRKDIR} |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and installs CMAKE |  | ||||||
| cmake_build() |  | ||||||
| { |  | ||||||
|     echo ">>> Building CMAKE ..." |  | ||||||
|     [ -z ${CLEAN} ] || rm -rf ${CMAKEDIR}/build-${GENERIC} |  | ||||||
|     mkdir -p ${CMAKEDIR}/build-${GENERIC} |  | ||||||
|     cd ${CMAKEDIR}/build-${GENERIC} |  | ||||||
|     ../bootstrap \ |  | ||||||
|         --prefix=${BINDIR} \ |  | ||||||
|         --parallel=${CORES} \ |  | ||||||
|         -- -DCMAKE_USE_OPENSSL=OFF |  | ||||||
|     make -j${CORES} |  | ||||||
|     make install |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function downloads CMAKE from VCS |  | ||||||
| cmake_fetch() |  | ||||||
| { |  | ||||||
|     if [ ! -d ${CMAKEDIR} ]; then |  | ||||||
|         echo ">>> Downloading CMAKE ..." |  | ||||||
|         git clone --depth 1 --branch ${CMAKETAG} ${CMAKEVCS} ${CMAKEDIR} |  | ||||||
|         cd ${CMAKEDIR} |  | ||||||
|         apply_patches ${CMAKEDIR##*/} ${CMAKETAG} |  | ||||||
|         cd ${WRKDIR} |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and install LLVM |  | ||||||
| llvm_build() |  | ||||||
| { |  | ||||||
|     echo ">>> Building LLVM ..." |  | ||||||
|     [ -z ${CLEAN} ] || rm -rf ${LLVMDIR}/llvm/build |  | ||||||
|     LLVM_ARCHS=() |  | ||||||
|     for ARCH in ${ARCHS}; do |  | ||||||
|         case ${ARCH} in |  | ||||||
|             "aarch64") |  | ||||||
|                 LLVM_ARCHS+=( "AArch64" ) |  | ||||||
|                 ;; |  | ||||||
|             "armv7") |  | ||||||
|                 LLVM_ARCHS+=( "ARM" ) |  | ||||||
|                 ;; |  | ||||||
|             "i686"|"x86_64") |  | ||||||
|                 LLVM_ARCHS+=( "X86" ) |  | ||||||
|                 ;; |  | ||||||
|         esac |  | ||||||
|     done |  | ||||||
|     LLVM_ARCHS=( $(for ARCH in ${LLVM_ARCHS[@]}; do echo ${ARCH}; done | sort -u) ) |  | ||||||
|     cd ${LLVMDIR}/llvm/tools |  | ||||||
|     for UTIL in clang lld; do |  | ||||||
|         if [ ! -e ${UTIL} ]; then |  | ||||||
|             ln -sf ../../${UTIL} . |  | ||||||
|         fi |  | ||||||
|     done |  | ||||||
|     mkdir -p ${LLVMDIR}/llvm/build |  | ||||||
|     cd ${LLVMDIR}/llvm/build |  | ||||||
|     cmake -G Ninja \ |  | ||||||
|         -DCMAKE_BUILD_TYPE="Release" \ |  | ||||||
|         -DCMAKE_INSTALL_PREFIX=${BINDIR} \ |  | ||||||
|         -DLLDB_INCLUDE_TESTS=FALSE \ |  | ||||||
|         -DLLVM_ENABLE_ASSERTIONS=FALSE \ |  | ||||||
|         -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;lldb" \ |  | ||||||
|         -DLLVM_INSTALL_TOOLCHAIN_ONLY=ON \ |  | ||||||
|         -DLLVM_LINK_LLVM_DYLIB=ON \ |  | ||||||
|         -DLLVM_TARGETS_TO_BUILD="$(echo ${LLVM_ARCHS[@]} | tr ' ' ';')" \ |  | ||||||
|         -DLLVM_TOOLCHAIN_TOOLS="llvm-addr2line;llvm-ar;llvm-as;llvm-cov;llvm-cvtres;llvm-dlltool;llvm-lib;llvm-ml;llvm-nm;llvm-objdump;llvm-objcopy;llvm-pdbutil;llvm-profdata;llvm-ranlib;llvm-rc;llvm-readelf;llvm-readobj;llvm-strings;llvm-strip;llvm-symbolizer;llvm-windres" \ |  | ||||||
|         .. |  | ||||||
|         ninja install/strip |  | ||||||
|         cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and install LIBCXX & LIBUNWIND |  | ||||||
| llvm_build_libs() |  | ||||||
| { |  | ||||||
|     echo ">>> Building LLVM libraries (libcxx) ..." |  | ||||||
|     for ARCH in ${ARCHS}; do |  | ||||||
|         [ -z ${CLEAN} ] || rm -rf ${LLVMDIR}/runtimes/build-${ARCH} |  | ||||||
|         mkdir -p ${LLVMDIR}/runtimes/build-${ARCH} |  | ||||||
|         cd ${LLVMDIR}/runtimes/build-${ARCH} |  | ||||||
|         cmake -G Ninja \ |  | ||||||
|             -DCMAKE_BUILD_TYPE="Release" \ |  | ||||||
|             -DCMAKE_INSTALL_PREFIX="${BINDIR}/${ARCH}-w64-mingw32" \ |  | ||||||
|             -DCMAKE_AR="${BINDIR}/bin/llvm-ar" \ |  | ||||||
|             -DCMAKE_C_COMPILER="${BINDIR}/bin/${ARCH}-w64-mingw32-clang" \ |  | ||||||
|             -DCMAKE_C_COMPILER_WORKS=1 \ |  | ||||||
|             -DCMAKE_C_FLAGS_INIT=-mguard=cf \ |  | ||||||
|             -DCMAKE_CXX_COMPILER="${BINDIR}/bin/${ARCH}-w64-mingw32-clang++" \ |  | ||||||
|             -DCMAKE_CXX_COMPILER_TARGET=${ARCH}-w64-windows-gnu \ |  | ||||||
|             -DCMAKE_CXX_COMPILER_WORKS=1 \ |  | ||||||
|             -DCMAKE_CXX_FLAGS_INIT=-mguard=cf \ |  | ||||||
|             -DCMAKE_CROSSCOMPILING=TRUE \ |  | ||||||
|             -DCMAKE_RANLIB="${BINDIR}/bin/llvm-ranlib" \ |  | ||||||
|             -DCMAKE_SYSTEM_NAME="Windows" \ |  | ||||||
|             -DLLVM_PATH="${LLVMDIR}/llvm" \ |  | ||||||
|             -DLLVM_ENABLE_RUNTIMES="libunwind;libcxxabi;libcxx" \ |  | ||||||
|             -DLIBUNWIND_USE_COMPILER_RT=TRUE \ |  | ||||||
|             -DLIBUNWIND_ENABLE_SHARED=TRUE \ |  | ||||||
|             -DLIBUNWIND_ENABLE_STATIC=TRUE \ |  | ||||||
|             -DLIBCXX_USE_COMPILER_RT=ON \ |  | ||||||
|             -DLIBCXX_ENABLE_SHARED=TRUE \ |  | ||||||
|             -DLIBCXX_ENABLE_STATIC=TRUE \ |  | ||||||
|             -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF \ |  | ||||||
|             -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=TRUE \ |  | ||||||
|             -DLIBCXX_CXX_ABI="libcxxabi" \ |  | ||||||
|             -DLIBCXX_LIBDIR_SUFFIX="" \ |  | ||||||
|             -DLIBCXX_INCLUDE_TESTS=FALSE \ |  | ||||||
|             -DLIBCXX_ENABLE_ABI_LINKER_SCRIPT=FALSE \ |  | ||||||
|             -DLIBCXXABI_USE_COMPILER_RT=ON \ |  | ||||||
|             -DLIBCXXABI_ENABLE_SHARED=OFF \ |  | ||||||
|             -DLIBCXXABI_LIBDIR_SUFFIX="" \ |  | ||||||
|             -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ |  | ||||||
|             .. |  | ||||||
|         ninja |  | ||||||
|         ninja install |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and install LLVM runtime |  | ||||||
| llvm_build_runtime() |  | ||||||
| { |  | ||||||
|     echo ">>> Building LLVM compiler runtime ..." |  | ||||||
|     for ARCH in ${ARCHS}; do |  | ||||||
|         [ -z ${CLEAN} ] || rm -rf ${LLVMDIR}/compiler-rt/build-${ARCH} |  | ||||||
|         mkdir -p ${LLVMDIR}/compiler-rt/build-${ARCH} |  | ||||||
|         cd ${LLVMDIR}/compiler-rt/build-${ARCH} |  | ||||||
|         cmake -G Ninja \ |  | ||||||
|             -DCMAKE_BUILD_TYPE="Release" \ |  | ||||||
|             -DCMAKE_AR="${BINDIR}/bin/llvm-ar" \ |  | ||||||
|             -DCMAKE_C_COMPILER="${BINDIR}/bin/${ARCH}-w64-mingw32-clang" \ |  | ||||||
|             -DCMAKE_C_COMPILER_TARGET="${ARCH}-windows-gnu" \ |  | ||||||
|             -DCMAKE_C_FLAGS_INIT="-mguard=cf" \ |  | ||||||
|             -DCMAKE_CXX_COMPILER="${BINDIR}/bin/${ARCH}-w64-mingw32-clang++" \ |  | ||||||
|             -DCMAKE_CXX_FLAGS_INIT="-mguard=cf" \ |  | ||||||
|             -DCMAKE_FIND_ROOT_PATH="${BINDIR}/${ARCH}-w64-mingw32" \ |  | ||||||
|             -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ |  | ||||||
|             -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY \ |  | ||||||
|             -DCMAKE_INSTALL_PREFIX=$(${BINDIR}/bin/${ARCH}-w64-mingw32-clang --print-resource-dir) \ |  | ||||||
|             -DCMAKE_RANLIB="${BINDIR}/bin/llvm-ranlib" \ |  | ||||||
|             -DCMAKE_SYSTEM_NAME="Windows" \ |  | ||||||
|             -DCOMPILER_RT_BUILD_BUILTINS=TRUE \ |  | ||||||
|             -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE \ |  | ||||||
|             -DCOMPILER_RT_USE_BUILTINS_LIBRARY=TRUE \ |  | ||||||
|             -DLLVM_CONFIG_PATH="" \ |  | ||||||
|             -DSANITIZER_CXX_ABI="libc++" \ |  | ||||||
|             ../lib/builtins |  | ||||||
|             ninja |  | ||||||
|             ninja install |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function downloads LLVM from VCS |  | ||||||
| llvm_fetch() |  | ||||||
| { |  | ||||||
|     if [ ! -d ${LLVMDIR} ]; then |  | ||||||
|         echo ">>> Downloading LLVM ..." |  | ||||||
|         git clone --depth 1 --branch ${LLVMTAG} ${LLVMVCS} ${LLVMDIR} |  | ||||||
|         cd ${LLVMDIR} |  | ||||||
|         apply_patches ${LLVMDIR##*/} ${LLVMTAG##*-} |  | ||||||
|         cd ${WRKDIR} |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and install MAKE |  | ||||||
| make_build() |  | ||||||
| { |  | ||||||
|     echo ">>> Building Make ..." |  | ||||||
|     [ -z ${CLEAN} ] || rm -rf ${MAKEDIR}/build |  | ||||||
|     cd ${MAKEDIR} |  | ||||||
|     ./bootstrap |  | ||||||
|     sed -i "s/-Werror//" maintMakefile |  | ||||||
|     mkdir -p ${MAKEDIR}/build |  | ||||||
|     cd ${MAKEDIR}/build |  | ||||||
|     ../configure \ |  | ||||||
|         --prefix=${BINDIR} \ |  | ||||||
|         --disable-dependency-tracking \ |  | ||||||
|         --disable-silent-rules \ |  | ||||||
|         --program-prefix=g \ |  | ||||||
|         --without-guile |  | ||||||
|     make -j${CORES} |  | ||||||
|     make install |  | ||||||
|     if [ ! -e ${BINDIR}/bin/make ]; then |  | ||||||
|         ln -sf gmake ${BINDIR}/bin/make |  | ||||||
|     fi |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function downloads MAKE from VCS |  | ||||||
| make_fetch() |  | ||||||
| { |  | ||||||
|     if [ ! -d ${MAKEDIR} ]; then |  | ||||||
|         echo ">>> Downloading Make ..." |  | ||||||
|         git clone --depth 1 --branch ${MAKETAG} ${MAKEVCS} ${MAKEDIR} |  | ||||||
|         cd ${MAKEDIR} |  | ||||||
|         apply_patches ${MAKEDIR##*/} ${MAKETAG} |  | ||||||
|         cd ${WRKDIR} |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and installs MINGW CRT |  | ||||||
| mingw_build_crt() |  | ||||||
| { |  | ||||||
|     for ARCH in ${ARCHS}; do |  | ||||||
|         echo ">>> Building Mingw-W64 (CRT) for ${ARCH} ..." |  | ||||||
|         [ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-crt/build-${ARCH} |  | ||||||
|         mkdir -p ${MINGWDIR}/mingw-w64-crt/build-${ARCH} |  | ||||||
|         cd ${MINGWDIR}/mingw-w64-crt/build-${ARCH} |  | ||||||
|         case ${ARCH} in |  | ||||||
|             "aarch64") |  | ||||||
|                 FLAGS="--disable-lib32 --disable-lib64 --enable-libarm64" |  | ||||||
|                 ;; |  | ||||||
|             "armv7") |  | ||||||
|                 FLAGS="--disable-lib32 --disable-lib64 --enable-libarm32" |  | ||||||
|                 ;; |  | ||||||
|             "i686") |  | ||||||
|                 FLAGS="--enable-lib32 --disable-lib64" |  | ||||||
|                 ;; |  | ||||||
|             "x86_64") |  | ||||||
|                 FLAGS="--disable-lib32 --enable-lib64" |  | ||||||
|                 ;; |  | ||||||
|         esac |  | ||||||
|         ORIGPATH="${PATH}" |  | ||||||
|         PATH="${BINDIR}/bin:${PATH}" |  | ||||||
|         ../configure \ |  | ||||||
|             --host=${ARCH}-w64-mingw32 \ |  | ||||||
|             --prefix=${BINDIR}/${ARCH}-w64-mingw32 \ |  | ||||||
|             --with-sysroot=${BINDIR} \ |  | ||||||
|             --with-default-msvcrt=${MINGWLIB} \ |  | ||||||
|             --enable-cfguard \ |  | ||||||
|             ${FLAGS} |  | ||||||
|         make -j${CORES} |  | ||||||
|         make install |  | ||||||
|         PATH="${ORIGPATH}" |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and installs MINGW headers |  | ||||||
| mingw_build_headers() |  | ||||||
| { |  | ||||||
|     echo ">>> Building Mingw-W64 (headers) ..." |  | ||||||
|     [ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-headers/build-${GENERIC} |  | ||||||
|     mkdir -p ${MINGWDIR}/mingw-w64-headers/build-${GENERIC} |  | ||||||
|     cd ${MINGWDIR}/mingw-w64-headers/build-${GENERIC} |  | ||||||
|     ../configure \ |  | ||||||
|         --prefix=${BINDIR}/${GENERIC} \ |  | ||||||
|         --enable-idl \ |  | ||||||
|         --with-default-msvcrt=${MINGWLIB} \ |  | ||||||
|         --with-default-win32-winnt=${MINGWNTV} |  | ||||||
|     make -j${CORES} |  | ||||||
|     make install |  | ||||||
|     for ARCH in ${ARCHS}; do |  | ||||||
|         mkdir -p ${BINDIR}/${ARCH}-w64-mingw32 |  | ||||||
|         if [ ! -e ${BINDIR}/${ARCH}-w64-mingw32/include ]; then |  | ||||||
|             ln -sfn ../${GENERIC}/include ${BINDIR}/${ARCH}-w64-mingw32/include |  | ||||||
|         fi |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and install MINGW libraries |  | ||||||
| mingw_build_libs() |  | ||||||
| { |  | ||||||
|     for LIB in libmangle winpthreads winstorecompat; do |  | ||||||
|         echo ">>> Building Mingw-w64 (libs) for ${ARCH} ..." |  | ||||||
|         for ARCH in ${ARCHS}; do |  | ||||||
|             [ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-libraries/${LIB}/build-${ARCH} |  | ||||||
|             mkdir -p ${MINGWDIR}/mingw-w64-libraries/${LIB}/build-${ARCH} |  | ||||||
|             cd ${MINGWDIR}/mingw-w64-libraries/${LIB}/build-${ARCH} |  | ||||||
|             ORIGPATH="${PATH}" |  | ||||||
|             PATH="${BINDIR}/bin:${PATH}" |  | ||||||
|             ../configure \ |  | ||||||
|                 --host=${ARCH}-w64-mingw32 \ |  | ||||||
|                 --prefix=${BINDIR}/${ARCH}-w64-mingw32 \ |  | ||||||
|                 --libdir=${BINDIR}/${ARCH}-w64-mingw32/lib \ |  | ||||||
|                 CFLAGS="-O2 -mguard=cf" \ |  | ||||||
|                 CXXFLAGS="-O2 -mguard=cf" |  | ||||||
|             make -j${CORES} |  | ||||||
|             make install |  | ||||||
|             PATH="${ORIGPATH}" |  | ||||||
|         done |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and installs MINGW tools |  | ||||||
| mingw_build_tools() |  | ||||||
| { |  | ||||||
|     for TOOL in gendef genidl genlib genpeimg widl; do |  | ||||||
|         for ARCH in ${ARCHS}; do |  | ||||||
|             echo ">>> Building Mingw-w64 (tools) for ${ARCH} ..." |  | ||||||
|             [ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-tools/${TOOL}/build-${ARCH} |  | ||||||
|             mkdir -p ${MINGWDIR}/mingw-w64-tools/${TOOL}/build-${ARCH} |  | ||||||
|             cd ${MINGWDIR}/mingw-w64-tools/${TOOL}/build-${ARCH} |  | ||||||
|             ../configure \ |  | ||||||
|                 --target=${ARCH}-w64-mingw32 \ |  | ||||||
|                 --prefix=${BINDIR} |  | ||||||
|             make -j${CORES} |  | ||||||
|             make install |  | ||||||
|             if [ -e ${BINDIR}/bin/${TOOL} ]; then |  | ||||||
|                 mv ${BINDIR}/bin/${TOOL} ${BINDIR}/bin/${ARCH}-w64-mingw32-${TOOL} |  | ||||||
|             fi |  | ||||||
|         done |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function downloads MINGW from VCS |  | ||||||
| mingw_fetch() |  | ||||||
| { |  | ||||||
|     if [ ! -d ${MINGWDIR} ]; then |  | ||||||
|         echo ">>> Downloading MinGW-w64 ..." |  | ||||||
|         git clone --depth 1 --branch ${MINGWTAG} ${MINGWVCS} ${MINGWDIR} |  | ||||||
|         cd ${MINGWDIR} |  | ||||||
|         apply_patches ${MINGWDIR##*/} ${MINGWTAG} |  | ||||||
|         cd ${WRKDIR} |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and installs NINJA |  | ||||||
| ninja_build() |  | ||||||
| { |  | ||||||
|     echo ">>> Building NINJA ..." |  | ||||||
|     [ -z ${CLEAN} ] || rm -rf ${NINJADIR}/build-${GENERIC} |  | ||||||
|     mkdir -p ${NINJADIR}/build-${GENERIC} |  | ||||||
|     cd ${NINJADIR}/build-${GENERIC} |  | ||||||
|     ../configure.py --bootstrap |  | ||||||
|     install ninja ${BINDIR}/bin/ |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function downloads NINJA from VCS |  | ||||||
| ninja_fetch() |  | ||||||
| { |  | ||||||
|     if [ ! -d ${NINJADIR} ]; then |  | ||||||
|         echo ">>> Downloading NINJA ..." |  | ||||||
|         git clone --depth 1 --branch ${NINJATAG} ${NINJAVCS} ${NINJADIR} |  | ||||||
|         cd ${NINJADIR} |  | ||||||
|         apply_patches ${NINJADIR##*/} ${NINJATAG} |  | ||||||
|         cd ${WRKDIR} |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function compiles and install WINE tools |  | ||||||
| wine_build() |  | ||||||
| { |  | ||||||
|     echo ">>> Building Wine ..." |  | ||||||
|     mkdir -p ${WINEDIR}/build |  | ||||||
|     cd ${WINEDIR}/build |  | ||||||
|     ../configure \ |  | ||||||
|         -enable-win64 \ |  | ||||||
|         --without-freetype \ |  | ||||||
|         --without-x |  | ||||||
|     for TOOL in winedump wmc wrc; do |  | ||||||
|         make -j${CORES} tools/${TOOL}/all |  | ||||||
|         cp tools/${TOOL}/${TOOL} ${BINDIR}/bin/ |  | ||||||
|         for ARCH in ${ARCHS}; do |  | ||||||
|             if [ ! -e ${BINDIR}/bin/${ARCH}-w64-mingw32-${TOOL} ]; then |  | ||||||
|                 ln -sf ${TOOL} ${BINDIR}/bin/${ARCH}-w64-mingw32-${TOOL} |  | ||||||
|             fi |  | ||||||
|         done |  | ||||||
|     done |  | ||||||
|     cd ${WRKDIR} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function downloads WINE from VCS |  | ||||||
| wine_fetch() |  | ||||||
| { |  | ||||||
|     if [ ! -d ${WINEDIR} ]; then |  | ||||||
|         echo ">>> Downloading WINE ..." |  | ||||||
|         git clone --depth 1 --branch ${WINETAG} ${WINEVCS} ${WINEDIR} |  | ||||||
|         cd ${WINEDIR} |  | ||||||
|         apply_patches ${WINEDIR##*/} ${WINETAG##*-} |  | ||||||
|         cd ${WRKDIR} |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # This function installs XTCHAIN scripts, wrappers and symlinks |  | ||||||
| xtchain_build() |  | ||||||
| { |  | ||||||
|     echo ">>> Building XTchain ..." |  | ||||||
|     mkdir -p ${BINDIR}/bin |  | ||||||
|     mkdir -p ${BINDIR}/lib/xtchain |  | ||||||
|     mkdir -p ${BINDIR}/${GENERIC}/bin |  | ||||||
|     cp ${WRKDIR}/scripts/*-wrapper ${BINDIR}/${GENERIC}/bin |  | ||||||
|     for ARCH in ${ARCHS}; do |  | ||||||
|         for EXEC in c++ c11 c99 cc clang clang++ g++ gcc; do |  | ||||||
|             ln -sf ../${GENERIC}/bin/clang-target-wrapper ${BINDIR}/bin/${ARCH}-w64-mingw32-${EXEC} |  | ||||||
|         done |  | ||||||
|         for EXEC in addr2line ar as nm objcopy pdbutil ranlib rc strings strip; do |  | ||||||
|             ln -sf llvm-${EXEC} ${BINDIR}/bin/${ARCH}-w64-mingw32-${EXEC} |  | ||||||
|         done |  | ||||||
|         for EXEC in dlltool ld objdump; do |  | ||||||
|             ln -sf ../${GENERIC}/bin/${EXEC}-wrapper ${BINDIR}/bin/${ARCH}-w64-mingw32-${EXEC} |  | ||||||
|         done |  | ||||||
|         for EXEC in bin2c exetool windres xtcspecc; do |  | ||||||
|             if [ ! -e ${BINDIR}/bin/${EXEC} ]; then |  | ||||||
|                 gcc ${WRKDIR}/tools/${EXEC}.c -o ${BINDIR}/bin/${EXEC} |  | ||||||
|             fi |  | ||||||
|             ln -sf ${EXEC} ${BINDIR}/bin/${ARCH}-w64-mingw32-${EXEC} |  | ||||||
|         done |  | ||||||
|     done |  | ||||||
|     cp ${WRKDIR}/scripts/xtclib ${BINDIR}/lib/xtchain/ |  | ||||||
|     cp ${WRKDIR}/scripts/xtchain ${BINDIR}/ |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Exit immediately on any failure |  | ||||||
| set -e |  | ||||||
|  |  | ||||||
| # Check number of CPU cores available |  | ||||||
| if [[ ! -n ${CORES} ]]; then |  | ||||||
| 	: ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} |  | ||||||
| 	: ${CORES:=$(nproc 2>/dev/null)} |  | ||||||
| 	: ${CORES:=1} |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # Create working directories |  | ||||||
| mkdir -p ${BINDIR} |  | ||||||
| mkdir -p ${SRCDIR} |  | ||||||
|  |  | ||||||
| # XTchain |  | ||||||
| xtchain_build |  | ||||||
|  |  | ||||||
| # Download LLVM |  | ||||||
| llvm_fetch |  | ||||||
|  |  | ||||||
| # Build and install LLVM |  | ||||||
| llvm_build |  | ||||||
|  |  | ||||||
| # Download Mingw-W64 |  | ||||||
| mingw_fetch |  | ||||||
|  |  | ||||||
| # Build and install Mingw-W64 headers |  | ||||||
| mingw_build_headers |  | ||||||
|  |  | ||||||
| # Build and install Mingw-W64 CRT |  | ||||||
| mingw_build_crt |  | ||||||
|  |  | ||||||
| # Build and install LLVM compiler runtime |  | ||||||
| llvm_build_runtime |  | ||||||
|  |  | ||||||
| # Build and install LLVM compiler libraries |  | ||||||
| llvm_build_libs |  | ||||||
|  |  | ||||||
| # Build and install Mingw-W64 libraries |  | ||||||
| mingw_build_libs |  | ||||||
|  |  | ||||||
| # Build and install Mingw-W64 tools |  | ||||||
| mingw_build_tools |  | ||||||
|  |  | ||||||
| # Download Binutils |  | ||||||
| binutils_fetch |  | ||||||
|  |  | ||||||
| # Build and install Binutils |  | ||||||
| binutils_build |  | ||||||
|  |  | ||||||
| # Download Wine |  | ||||||
| wine_fetch |  | ||||||
|  |  | ||||||
| # Build and install Wine tools |  | ||||||
| wine_build |  | ||||||
|  |  | ||||||
| # Download Make |  | ||||||
| make_fetch |  | ||||||
|  |  | ||||||
| # Build and install Make |  | ||||||
| make_build |  | ||||||
|  |  | ||||||
| # Download CMake |  | ||||||
| cmake_fetch |  | ||||||
|  |  | ||||||
| # Build and install CMake |  | ||||||
| cmake_build |  | ||||||
|  |  | ||||||
| # Download Ninja |  | ||||||
| ninja_fetch |  | ||||||
|  |  | ||||||
| # Build and install Ninja |  | ||||||
| ninja_build |  | ||||||
|  |  | ||||||
| # Remove unneeded files to save disk space |  | ||||||
| echo ">>> Removing unneeded files to save disk space ..." |  | ||||||
| rm -rf ${BINDIR}/{doc,include,share/{bash-completion,emacs,info,locale,man,vim}} |  | ||||||
| rm -rf ${BINDIR}/bin/amdgpu-arch,{clang-{check,exdef-mapping,import-test,offload-*,rename,scan-deps},diagtool,hmaptool,ld64.lld,modularize,nxptx-arch,wasm-ld} |  | ||||||
|  |  | ||||||
| # Save XT Toolchain version |  | ||||||
| cd ${WRKDIR} |  | ||||||
| : ${XTCVER:=$(git describe --exact-match --tags 2>/dev/null)} |  | ||||||
| : ${XTCVER:=DEVEL} |  | ||||||
| echo "${XTCVER}" > ${BINDIR}/Version |  | ||||||
|  |  | ||||||
| # Prepare archive |  | ||||||
| echo ">>> Creating toolchain archive ..." |  | ||||||
| tar -I 'zstd -19' -cpf xtchain-${XTCVER}-linux.tar.zst -C ${BINDIR} . |  | ||||||
							
								
								
									
										548
									
								
								build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										548
									
								
								build.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,548 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # PROJECT:     XTchain | ||||||
|  | # LICENSE:     See the COPYING.md in the top level directory | ||||||
|  | # FILE:        build.sh | ||||||
|  | # DESCRIPTION: Toolchain crosscompilation and assembly script | ||||||
|  | # DEVELOPERS:  Rafal Kupiec <belliash@codingworkshop.eu.org> | ||||||
|  | #              Aiken Harris <harraiken91@gmail.com> | ||||||
|  |  | ||||||
|  | # Working Directories | ||||||
|  | BINDIR="$(pwd)/binaries" | ||||||
|  | PCHDIR="$(pwd)/patches" | ||||||
|  | SRCDIR="$(pwd)/sources" | ||||||
|  | WRKDIR="$(pwd)" | ||||||
|  |  | ||||||
|  | # Architecture Settings | ||||||
|  | ARCHS="aarch64 armv7 i686 x86_64" | ||||||
|  |  | ||||||
|  | # Default Configuration | ||||||
|  | BUILD_JOBS=0 | ||||||
|  | BUILD_MINIMAL=0 | ||||||
|  | CLEAN_BUILD=0 | ||||||
|  | ENABLE_LLVM_ASSEMBLY=0 | ||||||
|  | LLVM_DYNAMIC_LINK=ON | ||||||
|  | SYSTEM_NAME=Linux | ||||||
|  | TARGET_SYSTEM=linux | ||||||
|  |  | ||||||
|  | # CMake Settings | ||||||
|  | CMAKEDIR="${SRCDIR}/cmake" | ||||||
|  | CMAKETAG="v4.1.1" | ||||||
|  | CMAKEVCS="https://gitlab.kitware.com/cmake/cmake.git" | ||||||
|  |  | ||||||
|  | # LLVM Settings | ||||||
|  | LLVMDIR="${SRCDIR}/llvm" | ||||||
|  | LLVMTAG="llvmorg-21.1.3" | ||||||
|  | LLVMVCS="https://github.com/llvm/llvm-project.git" | ||||||
|  |  | ||||||
|  | # Mtools Settings | ||||||
|  | MTOOLSDIR="${SRCDIR}/mtools" | ||||||
|  | MTOOLSTAG="v4.0.49" | ||||||
|  | MTOOLSVCS="https://github.com/xt-sys/mtools.git" | ||||||
|  |  | ||||||
|  | # Ninja Settings | ||||||
|  | NINJADIR="${SRCDIR}/ninja" | ||||||
|  | NINJATAG="v1.13.1" | ||||||
|  | NINJAVCS="https://github.com/ninja-build/ninja.git" | ||||||
|  |  | ||||||
|  | # Wine Settings | ||||||
|  | WINEDIR="${SRCDIR}/wine" | ||||||
|  | WINETAG="wine-10.15" | ||||||
|  | WINEVCS="https://github.com/wine-mirror/wine.git" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # This function applies a patches to the 3rd party project | ||||||
|  | apply_patches() | ||||||
|  | { | ||||||
|  |     local PACKAGE="${1}" | ||||||
|  |     local VERSION="${2}" | ||||||
|  |     if [ -d "${PCHDIR}/${PACKAGE}/${VERSION}" ]; then | ||||||
|  |         PATCHES="$(find ${PCHDIR}/${PACKAGE}/${VERSION} -name '*.diff' -o -name '*.patch' | sort -n)" | ||||||
|  |         echo ">>> Applying custom patches ..." | ||||||
|  |         for PATCH in ${PATCHES}; do | ||||||
|  |             if [ -f "${PATCH}" ] && [ -r "${PATCH}" ]; then | ||||||
|  |                 for PREFIX in {0..5}; do | ||||||
|  |                     if patch -i${PATCH} -p${PREFIX} --silent --dry-run >/dev/null; then | ||||||
|  |                         patch -i${PATCH} -p${PREFIX} --silent | ||||||
|  |                         echo ">>> Patch ${PATCH} applied ..." | ||||||
|  |                         break; | ||||||
|  |                     elif [ ${PREFIX} -ge 5 ]; then | ||||||
|  |                         echo "Patch ${PATCH} does not fit. Failed applying patch ..." | ||||||
|  |                         return 1 | ||||||
|  |                     fi | ||||||
|  |                 done | ||||||
|  |             fi | ||||||
|  |         done | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function compiles and installs CMAKE | ||||||
|  | cmake_build() | ||||||
|  | { | ||||||
|  |     local CMAKE_PARAMETERS="" | ||||||
|  |  | ||||||
|  |     # Clean old build if necessary | ||||||
|  |     [ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${WINEDIR}/build-${SYSTEM_NAME} | ||||||
|  |  | ||||||
|  |     # Additional, target-specific configuration options | ||||||
|  |     case "${SYSTEM_NAME}" in | ||||||
|  |         Windows) | ||||||
|  |             CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_C_COMPILER=${SYSTEM_HOST}-gcc -DCMAKE_CXX_COMPILER=${SYSTEM_HOST}-g++" | ||||||
|  |             CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_RC_COMPILER=${SYSTEM_HOST}-windres" | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # Build CMake | ||||||
|  |     echo ">>> Building CMAKE ..." | ||||||
|  |     mkdir -p ${CMAKEDIR}/build-${SYSTEM_NAME} | ||||||
|  |     cd ${CMAKEDIR}/build-${SYSTEM_NAME} | ||||||
|  |     cmake \ | ||||||
|  |         -DCMAKE_BUILD_TYPE=Release \ | ||||||
|  |         -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ | ||||||
|  |         -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \ | ||||||
|  |         -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \ | ||||||
|  |         -DCMAKE_INSTALL_PREFIX=${BINDIR} \ | ||||||
|  |         -DCMAKE_SYSTEM_NAME=${SYSTEM_NAME} \ | ||||||
|  |         -DCMAKE_USE_OPENSSL=OFF \ | ||||||
|  |         ${CMAKE_PARAMETERS} \ | ||||||
|  |         .. | ||||||
|  |     cmake --build . --parallel ${BUILD_JOBS} | ||||||
|  |     cmake --install . | ||||||
|  |     cd ${WRKDIR} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function downloads CMAKE from VCS | ||||||
|  | cmake_fetch() | ||||||
|  | { | ||||||
|  |     if [ ! -d ${CMAKEDIR} ]; then | ||||||
|  |         echo ">>> Downloading CMAKE ..." | ||||||
|  |         git clone --depth 1 --branch ${CMAKETAG} ${CMAKEVCS} ${CMAKEDIR} | ||||||
|  |         cd ${CMAKEDIR} | ||||||
|  |         apply_patches ${CMAKEDIR##*/} ${CMAKETAG} | ||||||
|  |         cd ${WRKDIR} | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function compiles and install LLVM | ||||||
|  | llvm_build() | ||||||
|  | { | ||||||
|  |     local CMAKE_PARAMETERS="" | ||||||
|  |     local LLVM_ARCHS=() | ||||||
|  |  | ||||||
|  |     # Clean old build if necessary | ||||||
|  |     [ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${LLVMDIR}/llvm/build-${SYSTEM_NAME} | ||||||
|  |  | ||||||
|  |     # Set supported architectures | ||||||
|  |     for ARCH in ${ARCHS}; do | ||||||
|  |         case ${ARCH} in | ||||||
|  |             "aarch64") | ||||||
|  |                 LLVM_ARCHS+=( "AArch64" ) | ||||||
|  |                 ;; | ||||||
|  |             "armv7") | ||||||
|  |                 LLVM_ARCHS+=( "ARM" ) | ||||||
|  |                 ;; | ||||||
|  |             "i686"|"x86_64") | ||||||
|  |                 LLVM_ARCHS+=( "X86" ) | ||||||
|  |                 ;; | ||||||
|  |         esac | ||||||
|  |     done | ||||||
|  |     LLVM_ARCHS=( $(for ARCH in ${LLVM_ARCHS[@]}; do echo ${ARCH}; done | sort -u) ) | ||||||
|  |  | ||||||
|  |     # Disable LLVM assembly files (like BLAKE3 support) if not specified otherwise | ||||||
|  |     if [ "${ENABLE_LLVM_ASSEMBLY}" -ne 1 ]; then | ||||||
|  |         CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DLLVM_DISABLE_ASSEMBLY_FILES=ON" | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     # Additional, target-specific configuration options | ||||||
|  |     case "${SYSTEM_NAME}" in | ||||||
|  |         Windows) | ||||||
|  |             CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_EXE_LINKER_FLAGS=-lpthread -DCMAKE_SHARED_LINKER_FLAGS=-lpthread" | ||||||
|  |             CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_C_COMPILER_TARGET=${SYSTEM_HOST} -DCMAKE_CXX_COMPILER_TARGET=${SYSTEM_HOST}" | ||||||
|  |             CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_RC_COMPILER=${SYSTEM_HOST}-windres -DLLVM_HOST_TRIPLE=${SYSTEM_HOST}" | ||||||
|  |             CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_FIND_ROOT=$(dirname $(readlink -f $(command -v ${SYSTEM_HOST}-windres)))/../${SYSTEM_HOST}" | ||||||
|  |             CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_CXX_FLAGS=-femulated-tls" | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # Build LLVM | ||||||
|  |     echo ">>> Building LLVM ..." | ||||||
|  |     cd ${LLVMDIR}/llvm/tools | ||||||
|  |     for UTIL in clang lld; do | ||||||
|  |         if [ ! -e ${UTIL} ]; then | ||||||
|  |             ln -sf ../../${UTIL} . | ||||||
|  |         fi | ||||||
|  |     done | ||||||
|  |     mkdir -p ${LLVMDIR}/llvm/build-${SYSTEM_NAME} | ||||||
|  |     cd ${LLVMDIR}/llvm/build-${SYSTEM_NAME} | ||||||
|  |     cmake -G Ninja \ | ||||||
|  |         -DCMAKE_BUILD_TYPE="Release" \ | ||||||
|  |         -DCMAKE_C_COMPILER=clang \ | ||||||
|  |         -DCMAKE_CXX_COMPILER=clang++ \ | ||||||
|  |         -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ | ||||||
|  |         -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \ | ||||||
|  |         -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY \ | ||||||
|  |         -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \ | ||||||
|  |         -DCMAKE_INSTALL_PREFIX=${BINDIR} \ | ||||||
|  |         -DCMAKE_SYSTEM_NAME="${SYSTEM_NAME}" \ | ||||||
|  |         -DLLDB_INCLUDE_TESTS=OFF \ | ||||||
|  |         -DLLVM_ENABLE_ASSERTIONS=OFF \ | ||||||
|  |         -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;lldb" \ | ||||||
|  |         -DLLVM_INSTALL_TOOLCHAIN_ONLY=ON \ | ||||||
|  |         -DLLVM_BUILD_INSTRUMENTED=OFF \ | ||||||
|  |         -DLLVM_LINK_LLVM_DYLIB=${LLVM_DYNAMIC_LINK} \ | ||||||
|  |         -DLLVM_TARGETS_TO_BUILD="$(echo ${LLVM_ARCHS[@]} | tr ' ' ';')" \ | ||||||
|  |         -DLLVM_TOOLCHAIN_TOOLS="llvm-addr2line;llvm-ar;llvm-as;llvm-cov;llvm-cvtres;llvm-cxxfilt;llvm-dlltool;llvm-lib;llvm-ml;llvm-nm;llvm-objdump;llvm-objcopy;llvm-pdbutil;llvm-profdata;llvm-ranlib;llvm-rc;llvm-readelf;llvm-readobj;llvm-size;llvm-strings;llvm-strip;llvm-symbolizer;llvm-windres" \ | ||||||
|  |         -DLLVM_USE_LINKER=lld \ | ||||||
|  |         -DLLDB_ENABLE_PYTHON=OFF \ | ||||||
|  |         ${CMAKE_PARAMETERS} \ | ||||||
|  |         .. | ||||||
|  |     ninja -j ${BUILD_JOBS} install/strip | ||||||
|  |     cd ${WRKDIR} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function downloads LLVM from VCS | ||||||
|  | llvm_fetch() | ||||||
|  | { | ||||||
|  |     if [ ! -d ${LLVMDIR} ]; then | ||||||
|  |         echo ">>> Downloading LLVM ..." | ||||||
|  |         git clone --depth 1 --branch ${LLVMTAG} ${LLVMVCS} ${LLVMDIR} | ||||||
|  |         cd ${LLVMDIR} | ||||||
|  |         apply_patches ${LLVMDIR##*/} ${LLVMTAG##*-} | ||||||
|  |         cd ${WRKDIR} | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function compiles and installs MTOOLS | ||||||
|  | mtools_build() | ||||||
|  | { | ||||||
|  |     local CONFIGURE_PARAMETERS="" | ||||||
|  |     local EXTENSION="" | ||||||
|  |  | ||||||
|  |     # Clean old build if necessary | ||||||
|  |     [ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${MTOOLSDIR}/build-${SYSTEM_NAME} | ||||||
|  |  | ||||||
|  |     # Additional, target-specific configuration options | ||||||
|  |     case "${SYSTEM_NAME}" in | ||||||
|  |         Windows) | ||||||
|  |             CONFIGURE_PARAMETERS="${CONFIGURE_PARAMETERS} --host=${SYSTEM_HOST}" | ||||||
|  |             EXTENSION=".exe" | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # Build Mtools | ||||||
|  |     echo ">>> Building MTOOLS ..." | ||||||
|  |     mkdir -p ${MTOOLSDIR}/build-${SYSTEM_NAME} | ||||||
|  |     cd ${MTOOLSDIR}/build-${SYSTEM_NAME} | ||||||
|  |     ../configure ${CONFIGURE_PARAMETERS} | ||||||
|  |     make -j ${BUILD_JOBS} | ||||||
|  |     cp mtools${EXTENSION} ${BINDIR}/bin/ | ||||||
|  |     for TOOL in mcat mcd mcopy mdel mdir mformat minfo mlabel mmd mmove mpartition mrd mren mshowfat mtype mzip; do | ||||||
|  |         cp mtools${EXTENSION} ${BINDIR}/bin/${TOOL}${EXTENSION} | ||||||
|  |     done | ||||||
|  |     cd ${WRKDIR} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function downloads MTOOLS from VCS | ||||||
|  | mtools_fetch() | ||||||
|  | { | ||||||
|  |     if [ ! -d ${MTOOLSDIR} ]; then | ||||||
|  |         echo ">>> Downloading MTOOLS ..." | ||||||
|  |         git clone --depth 1 --branch ${MTOOLSTAG} ${MTOOLSVCS} ${MTOOLSDIR} | ||||||
|  |         cd ${MTOOLSDIR} | ||||||
|  |         apply_patches ${MTOOLSDIR##*/} ${MTOOLSTAG} | ||||||
|  |         cd ${WRKDIR} | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function compiles and installs NINJA | ||||||
|  | ninja_build() | ||||||
|  | { | ||||||
|  |     local EXTENSION="" | ||||||
|  |     local NINJA_CXX_COMPILER="" | ||||||
|  |     local NINJA_PLATFORM="" | ||||||
|  |  | ||||||
|  |     # Clean old build if necessary | ||||||
|  |     [ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${NINJADIR}/build-${SYSTEM_NAME} | ||||||
|  |  | ||||||
|  |     # Additional, target-specific configuration options | ||||||
|  |     case "${SYSTEM_NAME}" in | ||||||
|  |         Windows) | ||||||
|  |             EXTENSION=".exe" | ||||||
|  |             NINJA_CXX_COMPILER="${SYSTEM_HOST}-g++" | ||||||
|  |             NINJA_PLATFORM="mingw" | ||||||
|  |             ;; | ||||||
|  |         *) | ||||||
|  |             NINJA_CXX_COMPILER="clang++" | ||||||
|  |             NINJA_PLATFORM="linux" | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # Build Ninja | ||||||
|  |     echo ">>> Building NINJA ..." | ||||||
|  |     mkdir -p ${NINJADIR}/build-${SYSTEM_NAME} | ||||||
|  |     cd ${NINJADIR}/build-${SYSTEM_NAME} | ||||||
|  |     CXX=${NINJA_CXX_COMPILER} ../configure.py --platform=${NINJA_PLATFORM} | ||||||
|  |     ninja -j ${BUILD_JOBS} | ||||||
|  |     install ninja${EXTENSION} ${BINDIR}/bin/ | ||||||
|  |     cd ${WRKDIR} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function downloads NINJA from VCS | ||||||
|  | ninja_fetch() | ||||||
|  | { | ||||||
|  |     if [ ! -d ${NINJADIR} ]; then | ||||||
|  |         echo ">>> Downloading NINJA ..." | ||||||
|  |         git clone --depth 1 --branch ${NINJATAG} ${NINJAVCS} ${NINJADIR} | ||||||
|  |         cd ${NINJADIR} | ||||||
|  |         apply_patches ${NINJADIR##*/} ${NINJATAG} | ||||||
|  |         cd ${WRKDIR} | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Performs requirements check and prepares environment | ||||||
|  | prepare_environment() | ||||||
|  | { | ||||||
|  |     # Verify that the number of build jobs is a positive integer | ||||||
|  |     if [ -z "${BUILD_JOBS##*[!0-9]*}" ]; then | ||||||
|  |         echo "ERROR: Invalid number of jobs provided. Please enter a positive integer." | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     # Verify that all required tools are installed | ||||||
|  |     for APP in {clang,clang++,cmake,lld,ninja,x86_64-w64-mingw32-windres}; do | ||||||
|  |         which ${APP} &> /dev/null | ||||||
|  |         if [ $? -ne 0 ]; then | ||||||
|  |             echo "ERROR: ${APP} not found. Please install the required tool." | ||||||
|  |             exit 2 | ||||||
|  |         fi | ||||||
|  |     done | ||||||
|  |  | ||||||
|  |     # Set target-specific options | ||||||
|  |     case "${TARGET_SYSTEM}" in | ||||||
|  |         windows|*-mingw32) | ||||||
|  |             SYSTEM_NAME="Windows" | ||||||
|  |             SYSTEM_HOST="x86_64-w64-mingw32" | ||||||
|  |             ;; | ||||||
|  |         linux|*-linux-*) | ||||||
|  |             SYSTEM_NAME="Linux" | ||||||
|  |             ;; | ||||||
|  |         *) | ||||||
|  |             echo "ERROR: Invalid target system specified. Please choose a valid target system." | ||||||
|  |             exit 3 | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Prints usage help | ||||||
|  | print_usage() | ||||||
|  | { | ||||||
|  |     echo "USAGE: ${0} [--clean] [--enable-llvm-assembly] [--jobs=N] [--minimal] [--static-llvm] [--target={linux,windows}]" | ||||||
|  |     exit 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function compiles and install WINE tools | ||||||
|  | wine_build() | ||||||
|  | { | ||||||
|  |     local CONFIGURE_PARAMETERS="" | ||||||
|  |     local EXTENSION="" | ||||||
|  |  | ||||||
|  |     # Clean old build if necessary | ||||||
|  |     [ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${WINEDIR}/{build-${SYSTEM_NAME},build-tools} | ||||||
|  |  | ||||||
|  |     # Additional, target-specific configuration options | ||||||
|  |     case "${SYSTEM_NAME}" in | ||||||
|  |         Windows) | ||||||
|  |             CONFIGURE_PARAMETERS="${CONFIGURE_PARAMETERS} --host=${SYSTEM_HOST}" | ||||||
|  |             EXTENSION=".exe" | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # Build Wine (first configuration builds makedep) | ||||||
|  |     echo ">>> Building Wine ..." | ||||||
|  |     mkdir -p ${WINEDIR}/{build-${SYSTEM_NAME},build-tools} | ||||||
|  |     cd ${WINEDIR}/build-tools | ||||||
|  |     ../configure \ | ||||||
|  |         --enable-win64 \ | ||||||
|  |         --without-freetype \ | ||||||
|  |         --without-x | ||||||
|  |     cd ${WINEDIR}/build-${SYSTEM_NAME} | ||||||
|  |     ../configure \ | ||||||
|  |         --enable-tools \ | ||||||
|  |         --enable-win64 \ | ||||||
|  |         --with-wine-tools=${WINEDIR}/build-tools \ | ||||||
|  |         --without-freetype \ | ||||||
|  |         --without-x \ | ||||||
|  |         ${CONFIGURE_PARAMETERS} | ||||||
|  |     for TOOL in widl wmc wrc; do | ||||||
|  |         make -j ${BUILD_JOBS} tools/${TOOL}/all | ||||||
|  |         cp tools/${TOOL}/${TOOL}${EXTENSION} ${BINDIR}/bin/ | ||||||
|  |     done | ||||||
|  |     cd ${WRKDIR} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function downloads WINE from VCS | ||||||
|  | wine_fetch() | ||||||
|  | { | ||||||
|  |     if [ ! -d ${WINEDIR} ]; then | ||||||
|  |         echo ">>> Downloading WINE ..." | ||||||
|  |         git clone --depth 1 --branch ${WINETAG} ${WINEVCS} ${WINEDIR} | ||||||
|  |         cd ${WINEDIR} | ||||||
|  |         apply_patches ${WINEDIR##*/} ${WINETAG##*-} | ||||||
|  |         cd ${WRKDIR} | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function installs XTCHAIN tools and scripts | ||||||
|  | xtchain_build() | ||||||
|  | { | ||||||
|  |     # Target-specific configuration options | ||||||
|  |     case "${SYSTEM_NAME}" in | ||||||
|  |         Windows) | ||||||
|  |             CCOMPILER="${SYSTEM_HOST}-gcc" | ||||||
|  |             ;; | ||||||
|  |         *) | ||||||
|  |             CCOMPILER="clang" | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # Build XTchain tools | ||||||
|  |     echo ">>> Building XTchain tools ..." | ||||||
|  |     mkdir -p ${BINDIR}/bin | ||||||
|  |     mkdir -p ${BINDIR}/lib/xtchain | ||||||
|  |     for EXEC in bin2c diskimg exetool xtcspecc; do | ||||||
|  |         if [ ! -e ${BINDIR}/bin/${EXEC} ]; then | ||||||
|  |             ${CCOMPILER} ${WRKDIR}/tools/${EXEC}.c -o ${BINDIR}/bin/${EXEC} | ||||||
|  |         fi | ||||||
|  |     done | ||||||
|  |     cp ${WRKDIR}/scripts/xtclib* ${BINDIR}/lib/xtchain/ | ||||||
|  |     cp ${WRKDIR}/scripts/xtchain* ${BINDIR}/ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # This function generates XTCHAIN version file and produces tarball archive | ||||||
|  | xtchain_tarball() | ||||||
|  | { | ||||||
|  |     local EXTENSION="" | ||||||
|  |     local LIBDIR="" | ||||||
|  |  | ||||||
|  |     # Additional, target-specific configuration options | ||||||
|  |     case "${SYSTEM_NAME}" in | ||||||
|  |         Windows) | ||||||
|  |             EXTENSION=".exe" | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # Remove unneeded files to save disk space | ||||||
|  |     echo ">>> Removing unneeded files to save disk space ..." | ||||||
|  |     rm -rf ${BINDIR}/{doc,include,share/{bash-completion,emacs,info,locale,man,vim}} | ||||||
|  |     for EXEC in amdgpu-arch clang-check clang-exdef-mapping clang-import-test clang-offload-* clang-rename clang-scan-deps diagtool hmaptool ld64.lld modularize nxptx-arch wasm-ld; do | ||||||
|  |         rm -f ${BINDIR}/bin/${EXEC}${EXTENSION} | ||||||
|  |     done | ||||||
|  |  | ||||||
|  |     # Generate version file | ||||||
|  |     cd ${WRKDIR} | ||||||
|  |     : ${XTCVER:=$(git describe --exact-match --tags 2>/dev/null)} | ||||||
|  |     : ${XTCVER:=DEVEL} | ||||||
|  |     [ ${BUILD_MINIMAL} -eq 1 ] && XTCVER="${XTCVER}-lite" | ||||||
|  |     echo "${XTCVER}" > ${BINDIR}/Version | ||||||
|  |  | ||||||
|  |     # Windows target specific actions | ||||||
|  |     if [ "${SYSTEM_NAME}" == "Windows" ]; then | ||||||
|  |         # Replace symlinks with original files | ||||||
|  |         for LINK in $(find ${BINDIR}/bin -maxdepth 1 -type l); do | ||||||
|  |             cp -f --remove-destination $(readlink -e ${LINK}) ${LINK} | ||||||
|  |         done | ||||||
|  |  | ||||||
|  |         # Copy dynamic libraries | ||||||
|  |         if [ ${BUILD_MINIMAL} -eq 0 ]; then | ||||||
|  |             LIBDIR="$(dirname $(readlink -f $(command -v ${SYSTEM_HOST}-windres)))/../${SYSTEM_HOST}" | ||||||
|  |             for DLL in $(${SYSTEM_HOST}-objdump --private-headers ${BINDIR}/bin/cmake.exe | grep "DLL Name:" | cut -d' ' -f3 | grep "lib.*.dll"); do | ||||||
|  |                 find ${LIBDIR} -type f -name ${DLL} -exec cp {} ${BINDIR}/bin \; | ||||||
|  |             done | ||||||
|  |         fi | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     # Build tarball | ||||||
|  |     echo ">>> Creating toolchain archive ..." | ||||||
|  |     tar -I 'zstd -19' -cpf xtchain-${XTCVER}-${TARGET_SYSTEM}.tar.zst -C ${BINDIR} . | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Parse all arguments provided to the script | ||||||
|  | while [ $# -gt 0 ]; do | ||||||
|  |     case "$1" in | ||||||
|  |         --clean) | ||||||
|  |             # Performs clean build | ||||||
|  |             CLEAN_BUILD=1 | ||||||
|  |             ;; | ||||||
|  |         --enable-llvm-assembly) | ||||||
|  |             # Enables LLVM asembly files compilation (like BLAKE3) | ||||||
|  |             ENABLE_LLVM_ASSEMBLY=1 | ||||||
|  |             ;; | ||||||
|  |         --jobs=*) | ||||||
|  |             # Sets number of CPU cores used for compilation | ||||||
|  |             BUILD_JOBS="${1#*=}" | ||||||
|  |             ;; | ||||||
|  |         --minimal) | ||||||
|  |             BUILD_MINIMAL=1 | ||||||
|  |             ;; | ||||||
|  |         --static-llvm) | ||||||
|  |             # Compiles LLVM statically | ||||||
|  |             LLVM_DYNAMIC_LINK=OFF | ||||||
|  |             ;; | ||||||
|  |         --target=*) | ||||||
|  |             # Sets the target system for built toolchain (Linux or Windows) | ||||||
|  |             TARGET_SYSTEM="${1#*=}" | ||||||
|  |             ;; | ||||||
|  |         *) | ||||||
|  |             # Prints help if any other parameter given | ||||||
|  |             print_usage | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  |     shift | ||||||
|  | done | ||||||
|  |  | ||||||
|  | # Prepare environment | ||||||
|  | prepare_environment | ||||||
|  |  | ||||||
|  | # Exit immediately on any failure | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | # Check number of CPU cores available | ||||||
|  | if [ ${BUILD_JOBS} -eq 0 ]; then | ||||||
|  |     unset BUILD_JOBS | ||||||
|  |     : ${BUILD_JOBS:=$(sysctl -n hw.ncpu 2>/dev/null)} | ||||||
|  |     : ${BUILD_JOBS:=$(nproc 2>/dev/null)} | ||||||
|  |     : ${BUILD_JOBS:=1} | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Create working directories | ||||||
|  | mkdir -p ${BINDIR} | ||||||
|  | mkdir -p ${SRCDIR} | ||||||
|  |  | ||||||
|  | # Build XTchain tools | ||||||
|  | xtchain_build | ||||||
|  |  | ||||||
|  | # Download and build Wine tools | ||||||
|  | wine_fetch | ||||||
|  | wine_build | ||||||
|  |  | ||||||
|  | # Download and build GNU Mtools | ||||||
|  | mtools_fetch | ||||||
|  | mtools_build | ||||||
|  |  | ||||||
|  | if [ ${BUILD_MINIMAL} -eq 0 ]; then | ||||||
|  |     # Download and build LLVM | ||||||
|  |     llvm_fetch | ||||||
|  |     llvm_build | ||||||
|  |  | ||||||
|  |     # Download and build CMake | ||||||
|  |     cmake_fetch | ||||||
|  |     cmake_build | ||||||
|  |  | ||||||
|  |     # Download and build Ninja | ||||||
|  |     ninja_fetch | ||||||
|  |     ninja_build | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Generate tarball archive | ||||||
|  | xtchain_tarball | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| diff --git a/bfd/config.bfd b/bfd/config.bfd |  | ||||||
| index bdee53957c0..04fff6e7df4 100644 |  | ||||||
| --- a/bfd/config.bfd |  | ||||||
| +++ b/bfd/config.bfd |  | ||||||
| @@ -407,6 +407,12 @@ case "${targ}" in |  | ||||||
|      targ_selvecs="arm_pe_le_vec arm_pe_be_vec arm_pei_le_vec arm_pei_be_vec" |  | ||||||
|      targ_underscore=yes |  | ||||||
|      ;; |  | ||||||
| +  arm-*-mingw*) |  | ||||||
| +    targ_defvec=arm_pe_le_vec |  | ||||||
| +    targ_selvecs="arm_pe_le_vec arm_pe_be_vec arm_pei_le_vec arm_pei_be_vec" |  | ||||||
| +    targ_underscore=no |  | ||||||
| +    targ_cflags="-DARM_COFF_BUGFIX" |  | ||||||
| +    ;; |  | ||||||
|    arm-*-phoenix*) |  | ||||||
|      targ_defvec=arm_elf32_le_vec |  | ||||||
|      targ_selvecs=arm_elf32_be_vec |  | ||||||
| diff --git a/gas/configure.tgt b/gas/configure.tgt |  | ||||||
| index 3429f850d05..fa735da7ce6 100644 |  | ||||||
| --- a/gas/configure.tgt |  | ||||||
| +++ b/gas/configure.tgt |  | ||||||
| @@ -164,7 +164,7 @@ case ${generic_target} in |  | ||||||
|    arm-*-nto*)				fmt=elf ;; |  | ||||||
|    arm-wince-pe | arm-*-wince | arm*-*-mingw32ce* | arm*-*-cegcc*) |  | ||||||
|  					fmt=coff em=wince-pe ;; |  | ||||||
| -  arm-*-pe)				fmt=coff em=pe ;; |  | ||||||
| +  arm-*-pe | arm-*-mingw*)	fmt=coff em=pe ;; |  | ||||||
|    arm-*-fuchsia*)			fmt=elf ;; |  | ||||||
|    arm-*-haiku*)				fmt=elf em=haiku ;; |  | ||||||
|   |  | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake |  | ||||||
| index 818109f0b7..749377d193 100644 |  | ||||||
| --- a/Source/CMakeVersion.cmake |  | ||||||
| +++ b/Source/CMakeVersion.cmake |  | ||||||
| @@ -7,7 +7,7 @@ set(CMake_VERSION_IS_DIRTY 0) |  | ||||||
|   |  | ||||||
|  # Start with the full version number used in tags.  It has no dev info. |  | ||||||
|  set(CMake_VERSION |  | ||||||
| -  "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") |  | ||||||
| +  "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}-XTC") |  | ||||||
|  if(DEFINED CMake_VERSION_RC) |  | ||||||
|    set(CMake_VERSION "${CMake_VERSION}-rc${CMake_VERSION_RC}") |  | ||||||
|  endif() |  | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp | ||||||
|  | index c0b10797e..e971b8cfd 100644 | ||||||
|  | --- a/lldb/source/Host/windows/MainLoopWindows.cpp | ||||||
|  | +++ b/lldb/source/Host/windows/MainLoopWindows.cpp | ||||||
|  | @@ -58,7 +58,7 @@ public: | ||||||
|  |        // Keep trying to cancel ReadFile() until the thread exits. | ||||||
|  |        do { | ||||||
|  |          CancelIoEx(m_handle, /*lpOverlapped=*/NULL); | ||||||
|  | -      } while (WaitForSingleObject(m_monitor_thread.native_handle(), 1) == | ||||||
|  | +      } while (WaitForSingleObject((HANDLE)m_monitor_thread.native_handle(), 1) == | ||||||
|  |                 WAIT_TIMEOUT); | ||||||
|  |        m_monitor_thread.join(); | ||||||
|  |      } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp | ||||||
|  | index c0b10797e..e971b8cfd 100644 | ||||||
|  | --- a/lldb/source/Host/windows/MainLoopWindows.cpp | ||||||
|  | +++ b/lldb/source/Host/windows/MainLoopWindows.cpp | ||||||
|  | @@ -58,7 +58,7 @@ public: | ||||||
|  |        // Keep trying to cancel ReadFile() until the thread exits. | ||||||
|  |        do { | ||||||
|  |          CancelIoEx(m_handle, /*lpOverlapped=*/NULL); | ||||||
|  | -      } while (WaitForSingleObject(m_monitor_thread.native_handle(), 1) == | ||||||
|  | +      } while (WaitForSingleObject((HANDLE)m_monitor_thread.native_handle(), 1) == | ||||||
|  |                 WAIT_TIMEOUT); | ||||||
|  |        m_monitor_thread.join(); | ||||||
|  |      } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,42 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| # PROJECT:     XTchain |  | ||||||
| # LICENSE:     See the COPYING.md in the top level directory |  | ||||||
| # FILE:        scripts/clang-target-wrapper |  | ||||||
| # DESCRIPTION: CLANG Wrapper |  | ||||||
| # DEVELOPERS:  Martin Storsjo <martin@martin.st> |  | ||||||
| #              Rafal Kupiec <belliash@codingworkshop.eu.org> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Set basic variables |  | ||||||
| DIR="$(cd $(dirname $0) && pwd)" |  | ||||||
| CLANG="$DIR/clang" |  | ||||||
| BASENAME="$(basename $0)" |  | ||||||
| TARGET="${BASENAME%-*}" |  | ||||||
| EXECUTABLE="${BASENAME##*-}" |  | ||||||
| DEFAULT_TARGET="x86_64-w64-mingw32" |  | ||||||
| ARCH="${TARGET%%-*}" |  | ||||||
|  |  | ||||||
| # Set proper target |  | ||||||
| if [ "${TARGET}" = "${BASENAME}" ]; then |  | ||||||
|     TARGET="${DEFAULT_TARGET}" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # Set lang-specific flags |  | ||||||
| case ${EXECUTABLE} in |  | ||||||
|     "clang++"|"g++"|"c++") |  | ||||||
|         FLAGS="$FLAGS --driver-mode=g++" |  | ||||||
|         ;; |  | ||||||
|     *) |  | ||||||
|         FLAGS="" |  | ||||||
|         ;; |  | ||||||
| esac |  | ||||||
|  |  | ||||||
| # Set compiler flags |  | ||||||
| FLAGS="${FLAGS} -target ${TARGET}" |  | ||||||
| FLAGS="${FLAGS} -rtlib=compiler-rt" |  | ||||||
| FLAGS="${FLAGS} -stdlib=libc++" |  | ||||||
| FLAGS="${FLAGS} -fuse-ld=lld" |  | ||||||
| FLAGS="${FLAGS} -Qunused-arguments" |  | ||||||
|  |  | ||||||
| # Launch the compiler |  | ||||||
| $CLANG $FLAGS "$@" |  | ||||||
| @@ -1,42 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| # PROJECT:     XTchain |  | ||||||
| # LICENSE:     See the COPYING.md in the top level directory |  | ||||||
| # FILE:        scripts/dlltool-wrapper |  | ||||||
| # DESCRIPTION: DLLTOOL Wrapper |  | ||||||
| # DEVELOPERS:  Martin Storsjo <martin@martin.st> |  | ||||||
| #              Rafal Kupiec <belliash@codingworkshop.eu.org> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Set basic variables |  | ||||||
| DIR="$(cd $(dirname $0) && pwd)" |  | ||||||
| BASENAME="$(basename $0)" |  | ||||||
| TARGET="${BASENAME%-*}" |  | ||||||
| DEFAULT_TARGET="x86_64-w64-mingw32" |  | ||||||
|  |  | ||||||
| # Update PATH |  | ||||||
| export PATH="$DIR":"$PATH" |  | ||||||
|  |  | ||||||
| # Set proper target |  | ||||||
| if [ "${TARGET}" = "${BASENAME}" ]; then |  | ||||||
|     TARGET="${DEFAULT_TARGET}" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # Set target machine |  | ||||||
| ARCH="${TARGET%%-*}" |  | ||||||
| case $ARCH in |  | ||||||
|     aarch64) |  | ||||||
|         M="arm64" |  | ||||||
|         ;; |  | ||||||
|     armv7) |  | ||||||
|         M="arm" |  | ||||||
|         ;; |  | ||||||
|     i686) |  | ||||||
|         M="i386" |  | ||||||
|         ;; |  | ||||||
|     x86_64) |  | ||||||
|         M="i386:x86-64" |  | ||||||
|         ;; |  | ||||||
| esac |  | ||||||
|  |  | ||||||
| # Launch the utility |  | ||||||
| llvm-dlltool -m ${M} "$@" |  | ||||||
| @@ -1,42 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| # PROJECT:     XTchain |  | ||||||
| # LICENSE:     See the COPYING.md in the top level directory |  | ||||||
| # FILE:        scripts/ld-wrapper |  | ||||||
| # DESCRIPTION: LLD Wrapper |  | ||||||
| # DEVELOPERS:  Martin Storsjo <martin@martin.st> |  | ||||||
| #              Rafal Kupiec <belliash@codingworkshop.eu.org> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Set basic variables |  | ||||||
| DIR="$(cd $(dirname $0) && pwd)" |  | ||||||
| BASENAME="$(basename $0)" |  | ||||||
| TARGET="${BASENAME%-*}" |  | ||||||
| DEFAULT_TARGET="x86_64-w64-mingw32" |  | ||||||
|  |  | ||||||
| # Update PATH |  | ||||||
| export PATH="${DIR}":"${PATH}" |  | ||||||
|  |  | ||||||
| # Set proper target |  | ||||||
| if [ "${TARGET}" = "${BASENAME}" ]; then |  | ||||||
|     TARGET="${DEFAULT_TARGET}" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # Set target machine |  | ||||||
| ARCH="${TARGET%%-*}" |  | ||||||
| case ${ARCH} in |  | ||||||
|     aarch64) |  | ||||||
|         M="arm64pe" |  | ||||||
|         ;; |  | ||||||
|     armv7) |  | ||||||
|         M="thumb2pe" |  | ||||||
|         ;; |  | ||||||
|     i686) |  | ||||||
|         M="i386pe" |  | ||||||
|         ;; |  | ||||||
|     x86_64) |  | ||||||
|         M="i386pep" |  | ||||||
|         ;; |  | ||||||
| esac |  | ||||||
|  |  | ||||||
| # Launch the linker |  | ||||||
| ld.lld -m ${M} "$@" |  | ||||||
| @@ -1,46 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| # PROJECT:     XTchain |  | ||||||
| # LICENSE:     See the COPYING.md in the top level directory |  | ||||||
| # FILE:        scripts/objdump-wrapper |  | ||||||
| # DESCRIPTION: OBJDUMP Wrapper |  | ||||||
| # DEVELOPERS:  Martin Storsjo <martin@martin.st> |  | ||||||
| #              Rafal Kupiec <belliash@codingworkshop.eu.org> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Set basic variables |  | ||||||
| DIR="$(cd $(dirname $0) && pwd)" |  | ||||||
|  |  | ||||||
| # Update PATH |  | ||||||
| export PATH="$DIR":"$PATH" |  | ||||||
|  |  | ||||||
| # Libtool can try to run objdump -f and wants to see certain strings in |  | ||||||
| # the output, to accept it being a valid windows (import) library |  | ||||||
| if [ "$1" = "-f" ]; then |  | ||||||
|     llvm-readobj $2 | while read -r line; do |  | ||||||
|         case $line in |  | ||||||
|         File:*) |  | ||||||
|             file=$(echo $line | awk '{print $2}') |  | ||||||
|             ;; |  | ||||||
|         Format:*) |  | ||||||
|             format=$(echo $line | awk '{print $2}') |  | ||||||
|             case $format in |  | ||||||
|             COFF-i386) |  | ||||||
|                 format=pe-i386 |  | ||||||
|                 ;; |  | ||||||
|             COFF-x86-64) |  | ||||||
|                 format=pe-x86-64 |  | ||||||
|                 ;; |  | ||||||
|             COFF-ARM*) |  | ||||||
|                 # This is wrong; modern COFF armv7 isn't pe-arm-wince, and |  | ||||||
|                 # arm64 definitely isn't, but libtool wants to see this |  | ||||||
|                 # string (or some of the others) in order to accept it. |  | ||||||
|                 format=pe-arm-wince |  | ||||||
|                 ;; |  | ||||||
|             esac |  | ||||||
|             echo $file: file format $format |  | ||||||
|             ;; |  | ||||||
|         esac |  | ||||||
|     done |  | ||||||
| else |  | ||||||
|     llvm-objdump "$@" |  | ||||||
| fi |  | ||||||
| @@ -7,13 +7,13 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| # Get the absolute path to the XTchain | # Get the absolute path to the XTchain | ||||||
| export XTCDIR="$(realpath $(dirname ${0}))" | export XTCDIR="$(realpath $(dirname "${0}"))" | ||||||
|  |  | ||||||
| # Read the XTchain version | # Read the XTchain version | ||||||
| export XTCVER="$(cat ${XTCDIR}/Version)" | export XTCVER="$(cat "${XTCDIR}/Version")" | ||||||
|  |  | ||||||
| # Load the library | # Load the library | ||||||
| source ${XTCDIR}/lib/xtchain/xtclib | source "${XTCDIR}/lib/xtchain/xtclib" | ||||||
|  |  | ||||||
| # Set the target architecture | # Set the target architecture | ||||||
| : ${TARGET:=${1}} | : ${TARGET:=${1}} | ||||||
| @@ -41,4 +41,4 @@ export PFMAT3="\[\033[0;1;97;104m\]" | |||||||
| export PFMAT4="\[\033[0;94;49m\]" | export PFMAT4="\[\033[0;94;49m\]" | ||||||
| export PFMAT5="\[\033[1;38;5;74m\]" | export PFMAT5="\[\033[1;38;5;74m\]" | ||||||
| export PROMPT="\n${PFMAT1} XT Toolchain ${PFMAT2}${PFMAT3} \w ${PFMAT4}${PFMAT5} " | export PROMPT="\n${PFMAT1} XT Toolchain ${PFMAT2}${PFMAT3} \w ${PFMAT4}${PFMAT5} " | ||||||
| bash --rcfile <(echo 'source ~/.bashrc && export PS1="${PROMPT}" && cd ${SRCDIR}') | bash --rcfile <(echo 'export PS1="${PROMPT}" && cd "${SRCDIR}"') | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								scripts/xtchain.cmd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								scripts/xtchain.cmd
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | @echo off | ||||||
|  | powershell.exe -ExecutionPolicy Bypass -NoExit -File "%~dp0xtchain.ps1" | ||||||
							
								
								
									
										57
									
								
								scripts/xtchain.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								scripts/xtchain.ps1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | # PROJECT:     XTchain | ||||||
|  | # LICENSE:     See the COPYING.md in the top level directory | ||||||
|  | # FILE:        scripts/xtchain.ps1 | ||||||
|  | # DESCRIPTION: XTchain Entry Script | ||||||
|  | # DEVELOPERS:  Aiken Harris <harraiken91@gmail.com> | ||||||
|  |  | ||||||
|  | # Get the absolute path to the XTchain | ||||||
|  | $XTCDIR = Split-Path -Parent $MyInvocation.MyCommand.Definition | ||||||
|  |  | ||||||
|  | # Read the XTchain version | ||||||
|  | $env:XTCVER = Get-Content "${XTCDIR}\Version" | ||||||
|  |  | ||||||
|  | # Load the library (Make sure the xtclib.ps1 file is PowerShell compatible) | ||||||
|  | . "${XTCDIR}\lib\xtchain\xtclib.ps1" | ||||||
|  |  | ||||||
|  | # Set the target architecture | ||||||
|  | $env:TARGET = $args[0] | ||||||
|  | if (-not $env:TARGET) { $env:TARGET = "amd64" } | ||||||
|  |  | ||||||
|  | # Save the source directory | ||||||
|  | $SRCDIR = $args[1] | ||||||
|  | if (-not $SRCDIR) { $SRCDIR = (Get-Location).Path } | ||||||
|  |  | ||||||
|  | # Make sure the compiler flags are clean | ||||||
|  | $env:HOST = $null | ||||||
|  | $env:CFLAGS = $null | ||||||
|  | $env:CXXFLAGS = $null | ||||||
|  | $env:LDFLAGS = $null | ||||||
|  |  | ||||||
|  | # Update PATH | ||||||
|  | $env:PATH = "${XTCDIR}\bin;" + $env:PATH | ||||||
|  |  | ||||||
|  | # Display banner | ||||||
|  | version | ||||||
|  |  | ||||||
|  | # Invoke shell with fancy prompt | ||||||
|  | function global:prompt { | ||||||
|  |     $PROMPT = " XT Toolchain " | ||||||
|  |     $CWD = (Get-Location).Path | ||||||
|  |     $CHEVRON = [char]0xE0B0 | ||||||
|  |     $SEGMENTS = @( | ||||||
|  |         @{ TEXT = $PROMPT; BGCOLOR = "Blue"; FGCOLOR = "White" }, | ||||||
|  |         @{ TEXT = " $CWD ";     BGCOLOR = "DarkCyan";     FGCOLOR = "White" } | ||||||
|  |     ) | ||||||
|  |     for ($INDEX = 0; $INDEX -lt $SEGMENTS.Count; $INDEX++) { | ||||||
|  |         $SEGMENT = $SEGMENTS[$INDEX] | ||||||
|  |         $NEXTBG = if ($INDEX + 1 -lt $SEGMENTS.Count) { $SEGMENTS[$INDEX + 1].BGCOLOR } else { "Default" } | ||||||
|  |         Write-Host $SEGMENT.TEXT -NoNewLine -ForegroundColor $SEGMENT.FGCOLOR -BackgroundColor $SEGMENT.BGCOLOR | ||||||
|  |         if ($NEXTBG -ne "Default") { | ||||||
|  |             Write-Host $CHEVRON -NoNewLine -ForegroundColor $SEGMENT.BGCOLOR -BackgroundColor $NEXTBG | ||||||
|  |         } else { | ||||||
|  |             Write-Host $CHEVRON -NoNewLine -ForegroundColor $SEGMENT.BGCOLOR | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return " " | ||||||
|  | } | ||||||
|  | Set-Location -Path $SRCDIR | ||||||
| @@ -4,8 +4,20 @@ | |||||||
| # FILE:        scripts/xtclib | # FILE:        scripts/xtclib | ||||||
| # DESCRIPTION: XTchain library | # DESCRIPTION: XTchain library | ||||||
| # DEVELOPERS:  Rafal Kupiec <belliash@codingworkshop.eu.org> | # DEVELOPERS:  Rafal Kupiec <belliash@codingworkshop.eu.org> | ||||||
|  | #              Aiken Harris <harraiken91@gmail.com> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Prints XTChain banner | ||||||
|  | banner() | ||||||
|  | { | ||||||
|  |     local XTC_BANNER="XT Toolchain v${XTCVER} for Linux" | ||||||
|  |  | ||||||
|  |     printf "###############################################################################\n\n" | ||||||
|  |     printf "\033[33m%*s\033[00m\n\n" $(( (${#XTC_BANNER} + 80) / 2)) "${XTC_BANNER}" | ||||||
|  |     printf "###############################################################################\n\n" | ||||||
|  | } | ||||||
|  | export -f banner | ||||||
|  |  | ||||||
| # Sets the target architecture | # Sets the target architecture | ||||||
| charch() | charch() | ||||||
| { | { | ||||||
| @@ -54,8 +66,9 @@ export -f chbuild | |||||||
| # Prints help | # Prints help | ||||||
| help() | help() | ||||||
| { | { | ||||||
| 	version |     banner | ||||||
|     echo "XTChain defines an internal list of commands:" |     echo "XTChain defines an internal list of commands:" | ||||||
|  |     echo " * banner          - prints XTChain banner" | ||||||
|     echo " * charch [arch]   - sets the target CPU architecture [aarch64/armv7/i686/amd64]" |     echo " * charch [arch]   - sets the target CPU architecture [aarch64/armv7/i686/amd64]" | ||||||
|     echo " * chbuild [type]  - sets build type [debug/release]" |     echo " * chbuild [type]  - sets build type [debug/release]" | ||||||
|     echo " * help            - prints this message" |     echo " * help            - prints this message" | ||||||
| @@ -67,22 +80,36 @@ export -f help | |||||||
| # Displays version banner | # Displays version banner | ||||||
| version() | version() | ||||||
| { | { | ||||||
|     echo "###############################################################################" |     local XTCHAIN_EXTTOOLS=false | ||||||
|     echo "#                        XT Toolchain v${XTCVER} for Linux                        #" |  | ||||||
|     echo "#               by Rafal Kupiec <belliash@codingworkshop.eu.org>              #" |     if [ ! -f "${XTCDIR}/bin/clang" ] || [ "$(which clang)" != "${XTCDIR}/bin/clang" ] || [ $(echo ${XTCVER} | grep "min") ]; then | ||||||
|     echo "###############################################################################" |         XTCHAIN_EXTTOOLS=true | ||||||
|     echo |         for TOOL in {clang,clang++,cmake,lld-link,ninja}; do | ||||||
|     echo |             which ${TOOL} &> /dev/null | ||||||
|     echo "LLVM Compiler Version: $(${XTCDIR}/bin/clang --version | grep 'clang version' | cut -d' ' -f3)" |             if [ $? -ne 0 ]; then | ||||||
|     echo "LLVM Windres Utility Version: $(${XTCDIR}/bin/i686-w64-mingw32-windres -V | cut -d' ' -f6)" |                 echo "ERROR: You are using minimal version of XTChain and '${TOOL}' has been not found in your system!" | ||||||
|     echo "Mingw IDL Compiler Version: $(${XTCDIR}/bin/i686-w64-mingw32-widl -V | grep 'version' | cut -d' ' -f5)" |                 echo "ERROR: Please install all required tools." | ||||||
|     echo "Wine Message Compiler Version: $(${XTCDIR}/bin/wmc -V | grep 'version' | cut -d' ' -f5)" |                 exit 1 | ||||||
|     echo "Wine Resource Compiler Version: $(${XTCDIR}/bin/wrc --version | grep 'version' | cut -d' ' -f5)" |             fi | ||||||
|     echo |         done | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     banner | ||||||
|  |     echo -en "\nLLVM/Clang Compiler: $(clang --version | grep 'clang version' | cut -d' ' -f3) ($(which clang))" | ||||||
|  |     echo -en "\nLLVM/LLD Linker: $(lld-link --version | cut -d' ' -f2) ($(which lld-link))" | ||||||
|  |     echo -en "\nWine IDL Compiler: $(widl -V | grep 'version' | cut -d' ' -f5) ($(which widl))" | ||||||
|  |     echo -en "\nWine Message Compiler: $(wmc -V | grep 'version' | cut -d' ' -f5) ($(which wmc))" | ||||||
|  |     echo -en "\nWine Resource Compiler: $(wrc --version | grep 'version' | cut -d' ' -f5) ($(which wrc))" | ||||||
|  |     echo -en "\nXT SPEC Compiler: $(xtcspecc --help | grep Version | cut -d' ' -f5) ($(which xtcspecc))" | ||||||
|  |     echo -en "\nCMake Build System: $(cmake --version | grep 'cmake version' | cut -d' ' -f3) ($(which cmake))" | ||||||
|  |     echo -en "\nNinja Build System: $(ninja --version) ($(which ninja))" | ||||||
|  |     echo -en "\n\n" | ||||||
|  |  | ||||||
|     charch ${TARGET:-amd64} |     charch ${TARGET:-amd64} | ||||||
|     chbuild ${BUILD_TYPE:-DEBUG} |     chbuild ${BUILD_TYPE:-DEBUG} | ||||||
|     echo |  | ||||||
|     echo |     echo -en "\n\nFor a list of all supported commands, type 'help'" | ||||||
|  |     echo -en "\n-------------------------------------------------\n\n\n" | ||||||
| } | } | ||||||
| export -f version | export -f version | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										143
									
								
								scripts/xtclib.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								scripts/xtclib.ps1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | |||||||
|  | # PROJECT:     XTchain | ||||||
|  | # LICENSE:     See the COPYING.md in the top level directory | ||||||
|  | # FILE:        scripts/xtclib.ps1 | ||||||
|  | # DESCRIPTION: XTchain library | ||||||
|  | # DEVELOPERS:  Aiken Harris <harraiken91@gmail.com> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Prints XTChain banner | ||||||
|  | function banner { | ||||||
|  |     param() | ||||||
|  |      | ||||||
|  |     $XTC_BANNER = "XT Toolchain v${Env:XTCVER} for Windows" | ||||||
|  |  | ||||||
|  |     Write-Host "################################################################################" | ||||||
|  |     Write-Host | ||||||
|  |     Write-Host (' ' * [math]::Floor((80 - $XTC_BANNER.Length) / 2) + $XTC_BANNER) -ForegroundColor Yellow | ||||||
|  |     Write-Host | ||||||
|  |     Write-Host "################################################################################" | ||||||
|  |     Write-Host | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Sets the target architecture | ||||||
|  | function charch { | ||||||
|  |     param ( | ||||||
|  |         [string]$arch | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     if ([string]::IsNullOrWhiteSpace($arch)) { | ||||||
|  |         Write-Host "Syntax: charch [architecture]" | ||||||
|  |         return | ||||||
|  |     } | ||||||
|  |     switch -Regex ($arch) { | ||||||
|  |         "aarch64|arm64" { | ||||||
|  |             $Env:TARGET = "aarch64" | ||||||
|  |         } | ||||||
|  |         "arm|armv7" { | ||||||
|  |             $Env:TARGET = "armv7" | ||||||
|  |         } | ||||||
|  |         "i386|i486|i586|i686|x86" { | ||||||
|  |             $Env:TARGET = "i686" | ||||||
|  |         } | ||||||
|  |         "amd64|x64|x86_64" { | ||||||
|  |             $Env:TARGET = "amd64" | ||||||
|  |         } | ||||||
|  |         default { | ||||||
|  |             $Env:TARGET = "UNKNOWN" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     Write-Host "Target Architecture: $($Env:TARGET)" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Sets the build type | ||||||
|  | function chbuild { | ||||||
|  |     param ( | ||||||
|  |         [string]$buildType | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     if ([string]::IsNullOrWhiteSpace($buildType)) { | ||||||
|  |         Write-Host "Syntax: chbuild [DEBUG|RELEASE]" | ||||||
|  |         return | ||||||
|  |     } | ||||||
|  |     switch -Regex ($buildType.ToUpper()) { | ||||||
|  |         "RELEASE" { | ||||||
|  |             $Env:BUILD_TYPE = "RELEASE" | ||||||
|  |         } | ||||||
|  |         default { | ||||||
|  |             $Env:BUILD_TYPE = "DEBUG" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     Write-Host "Target build type: $($Env:BUILD_TYPE)" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Prints help | ||||||
|  | function help { | ||||||
|  |     banner | ||||||
|  |     Write-Host "XTChain defines an internal list of commands:" | ||||||
|  |     Write-Host " * banner          - prints XTChain banner" | ||||||
|  |     Write-Host " * charch [arch]   - sets the target CPU architecture [aarch64/armv7/i686/amd64]" | ||||||
|  |     Write-Host " * chbuild [type]  - sets build type [debug/release]" | ||||||
|  |     Write-Host " * help            - prints this message" | ||||||
|  |     Write-Host " * version         - prints XTChain and its components version" | ||||||
|  |     Write-Host " * xbuild          - builds an application with a Ninja build system" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Displays version banner | ||||||
|  | function version { | ||||||
|  |     param() | ||||||
|  |  | ||||||
|  |     [bool]$XTCHAIN_EXTTOOLS = $false | ||||||
|  |  | ||||||
|  |     if ((Test-Path "${Env:XTCDIR}/bin/clang") -and  | ||||||
|  |         ((Get-Command clang).Source -eq "${Env:XTCDIR}/bin/clang") -and | ||||||
|  |         ($Env:XTCVER -match "min")) { | ||||||
|  |         $XTCHAIN_EXTTOOLS = $true | ||||||
|  |         foreach ($TOOL in @("clang", "clang++", "cmake", "lld-link", "ninja")) { | ||||||
|  |             if (!(Get-Command $TOOL -ErrorAction SilentlyContinue)) { | ||||||
|  |                 Write-Error "You are using minimal version of XTChain and '${TOOL}' has been not found in your system!" | ||||||
|  |                 Write-Error "Please install all required tools." | ||||||
|  |                 return | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     banner | ||||||
|  |     Write-Host | ||||||
|  |     Write-Host "LLVM/Clang Compiler: $(clang --version | Select-String -Pattern "version (\d+\.\d+\.\d+)"  | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command clang).Source))" | ||||||
|  |     Write-Host "LLVM/LLD Linker: $(lld-link --version |  Select-String -Pattern "(\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command lld-link).Source))" | ||||||
|  |     Write-Host "Wine IDL Compiler: $(widl -V | Select-String -Pattern "version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command widl).Source))" | ||||||
|  |     Write-Host "Wine Message Compiler: $(wmc -V | Select-String -Pattern "version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command wmc).Source))" | ||||||
|  |     Write-Host "Wine Resource Compiler: $(wrc --version | Select-String -Pattern "version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command wrc).Source))" | ||||||
|  |     Write-Host "XT SPEC Compiler: $(xtcspecc --help | Select-String -Pattern "Version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command xtcspecc).Source))" | ||||||
|  |     Write-Host "CMake Build System: $(cmake --version | Select-String -Pattern "version (\d+\.\d+\.\d+)"  | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command cmake).Source))" | ||||||
|  |     Write-Host "Ninja Build System: $(ninja --version) ($($(Get-Command ninja).Source))" | ||||||
|  |     Write-Host | ||||||
|  |  | ||||||
|  |     $BUILD_TYPE = if ($null -eq $env:BUILD_TYPE -or $env:BUILD_TYPE -eq '') { 'DEBUG' } else { $env:BUILD_TYPE } | ||||||
|  |     $TARGET = if ($null -eq $env:TARGET -or $env:TARGET -eq '') { 'amd64' } else { $env:TARGET } | ||||||
|  |     charch $TARGET | ||||||
|  |     chbuild $BUILD_TYPE | ||||||
|  |  | ||||||
|  |     Write-Host | ||||||
|  |     Write-Host | ||||||
|  |     Write-Host "For a list of all supported commands, type 'help'" | ||||||
|  |     Write-Host "-------------------------------------------------" | ||||||
|  |     Write-Host | ||||||
|  |     Write-Host | ||||||
|  |     Write-Host | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Builds application (wrapper to Ninja) | ||||||
|  | function xbuild { | ||||||
|  |     if (-not (Test-Path build.arch)) { | ||||||
|  |         & ninja @args | ||||||
|  |     } else { | ||||||
|  |         $ARCH = Get-Content build.arch | ||||||
|  |         if ($ARCH -ne $Env:TARGET) { | ||||||
|  |             Write-Host "Build is configured for '$ARCH' while current target set to '$($Env:TARGET)'!" | ||||||
|  |             Write-Host "Cannot continue until conflict is resolved ..." | ||||||
|  |             return 1 | ||||||
|  |         } | ||||||
|  |         & ninja @args | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										759
									
								
								tools/diskimg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										759
									
								
								tools/diskimg.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,759 @@ | |||||||
|  | /** | ||||||
|  |  * PROJECT:     XTchain | ||||||
|  |  * LICENSE:     See COPYING.md in the top level directory | ||||||
|  |  * FILE:        tools/diskimg.c | ||||||
|  |  * DESCRIPTION: Disk Image manipulation tool | ||||||
|  |  * DEVELOPERS:  Rafal Kupiec <belliash@codingworkshop.eu.org> | ||||||
|  |  *              Aiken Harris <harraiken91@gmail.com> | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "xtchain.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static RESERVED_SECTOR_INFO Fat32ReservedMap[] = | ||||||
|  | { | ||||||
|  |     {0, "Main VBR"}, | ||||||
|  |     {1, "FSInfo Sector"}, | ||||||
|  |     {6, "Backup VBR"}, | ||||||
|  |     {7, "Backup FSInfo Sector"}, | ||||||
|  |     {-1, NULL} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Forward references */ | ||||||
|  | static void CopyData(const char *Image, long Offset, const char *SourceDir, const char *Relative); | ||||||
|  | static void CopyImageFile(const char *Image, long Offset, const char *SourceFile, const char *Relative); | ||||||
|  | static long DetermineExtraSector(long sectors_to_write); | ||||||
|  | long GetSectorFileSize(const char *FileName); | ||||||
|  | int LoadSectors(const char *FileName, uint8_t *Buffer, int SectorCount); | ||||||
|  | static void MakeDirectory(const char *Image, long Offset, const char *Relative); | ||||||
|  |  | ||||||
|  | /* Copies a directory recursively to the image */ | ||||||
|  | static void CopyData(const char *Image, long Offset, const char *SourceDir, const char *Relative) | ||||||
|  | { | ||||||
|  |     char Path[2048]; | ||||||
|  |     struct dirent *Entry; | ||||||
|  |     DIR *Directory; | ||||||
|  |     struct stat Stat; | ||||||
|  |     char new_rel[2048]; | ||||||
|  |  | ||||||
|  |     /* Create the directory in the image */ | ||||||
|  |     if(Relative[0] != '\0') | ||||||
|  |     { | ||||||
|  |         MakeDirectory(Image, Offset, Relative); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Open the source directory */ | ||||||
|  |     Directory = opendir(SourceDir); | ||||||
|  |     if(!Directory) | ||||||
|  |     { | ||||||
|  |         /* Failed to open directory */ | ||||||
|  |         perror("Failed to open source directory"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Read all entries in the directory */ | ||||||
|  |     while((Entry = readdir(Directory))) | ||||||
|  |     { | ||||||
|  |         /* Skip . and .. entries */ | ||||||
|  |         if(strcmp(Entry->d_name, ".") == 0 || strcmp(Entry->d_name, "..") == 0) | ||||||
|  |         { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Build the full path to the entry */ | ||||||
|  |         snprintf(Path, sizeof(Path), "%s%c%s", SourceDir, PATH_SEP, Entry->d_name); | ||||||
|  |  | ||||||
|  |         /* Stat the entry */ | ||||||
|  |         if(stat(Path, &Stat) == -1) | ||||||
|  |         { | ||||||
|  |             /* Failed to stat entry */ | ||||||
|  |             perror("Failed to stat file or directory"); | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Build the relative path to the entry */ | ||||||
|  |         if(Relative[0] != '\0') | ||||||
|  |         { | ||||||
|  |             snprintf(new_rel, sizeof(new_rel), "%s/%s", Relative, Entry->d_name); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             snprintf(new_rel, sizeof(new_rel), "%s", Entry->d_name); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Copy the entry to the image */ | ||||||
|  |         if(S_ISDIR(Stat.st_mode)) | ||||||
|  |         { | ||||||
|  |             /* Entry is a directory, copy it recursively */ | ||||||
|  |             CopyData(Image, Offset, Path, new_rel); | ||||||
|  |         } | ||||||
|  |         else if(S_ISREG(Stat.st_mode)) | ||||||
|  |         { | ||||||
|  |             /* Entry is a file, copy it */ | ||||||
|  |             CopyImageFile(Image, Offset, Path, new_rel); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Close the directory */ | ||||||
|  |     closedir(Directory); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Copies a file to the image */ | ||||||
|  | static void CopyImageFile(const char *Image, long Offset, const char *SourceFile, const char *Relative) | ||||||
|  | { | ||||||
|  |     char Command[4096]; | ||||||
|  |  | ||||||
|  |     /* Copy the file to the image */ | ||||||
|  |     snprintf(Command, sizeof(Command), "mcopy -i \"%s@@%ld\" \"%s\" \"::/%s\"", Image, Offset, SourceFile, Relative); | ||||||
|  |     if(system(Command) != 0) | ||||||
|  |     { | ||||||
|  |         /* Failed to copy file */ | ||||||
|  |         fprintf(stderr, "Faile to copy file '%s' to image\n", SourceFile); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Determines a safe sector to write extra VBR data to */ | ||||||
|  | static long DetermineExtraSector(long sectors_to_write) | ||||||
|  | { | ||||||
|  |     long Candidate; | ||||||
|  |     long Conflict; | ||||||
|  |     long Index; | ||||||
|  |     long LastSector; | ||||||
|  |  | ||||||
|  |     /* Start search from sector 1 (sector 0 is the main VBR) */ | ||||||
|  |     for(Candidate = 1; Candidate < 32; Candidate++) | ||||||
|  |     { | ||||||
|  |         /* Calculate the last sector to write */ | ||||||
|  |         LastSector = Candidate + sectors_to_write - 1; | ||||||
|  |         Conflict = 0; | ||||||
|  |  | ||||||
|  |         /* Check if it fits within the reserved region (32 sectors) */ | ||||||
|  |         if(LastSector >= 32) | ||||||
|  |         { | ||||||
|  |             /* The remaining space is not large enough */ | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Check for conflicts with critical sectors */ | ||||||
|  |         for(Index = 0; Fat32ReservedMap[Index].SectorNumber != -1; Index++) | ||||||
|  |         { | ||||||
|  |             if(Candidate <= Fat32ReservedMap[Index].SectorNumber && LastSector >= Fat32ReservedMap[Index].SectorNumber) | ||||||
|  |             { | ||||||
|  |                 /* Found a conflict */ | ||||||
|  |                 Conflict = 1; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Make sure there are no conflicts */ | ||||||
|  |         if(!Conflict) | ||||||
|  |         { | ||||||
|  |             /* Found a suitable slot */ | ||||||
|  |             return Candidate; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* No suitable slot found */ | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Gets the size of a file */ | ||||||
|  | long GetSectorFileSize(const char *FileName) | ||||||
|  | { | ||||||
|  |     FILE *File; | ||||||
|  |     long Size; | ||||||
|  |  | ||||||
|  |     /* Open the file in binary mode */ | ||||||
|  |     File = fopen(FileName, "rb"); | ||||||
|  |     if(!File) | ||||||
|  |     { | ||||||
|  |         /* Failed to open file */ | ||||||
|  |         perror("Failed to open file for size check"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Get the file size */ | ||||||
|  |     fseek(File, 0, SEEK_END); | ||||||
|  |     Size = ftell(File); | ||||||
|  |  | ||||||
|  |     /* Close the file and return the size */ | ||||||
|  |     fclose(File); | ||||||
|  |     return Size; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Loads one or more sectors from a file */ | ||||||
|  | int LoadSectors(const char *FileName, uint8_t *Buffer, int SectorCount) | ||||||
|  | { | ||||||
|  |     FILE *File; | ||||||
|  |     long FileSize; | ||||||
|  |     long BytesToRead = SectorCount * SECTOR_SIZE; | ||||||
|  |  | ||||||
|  |     /* Get and validate file size */ | ||||||
|  |     FileSize = GetSectorFileSize(FileName); | ||||||
|  |     if(FileSize < 0) | ||||||
|  |     { | ||||||
|  |         /* Failed to get file size */ | ||||||
|  |         perror("Failed to get file size"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     if(FileSize != BytesToRead) | ||||||
|  |     { | ||||||
|  |         fprintf(stderr, "Error: file '%s' must be exactly %ld bytes, but is %ld bytes.\n", FileName, BytesToRead, FileSize); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Open the file in binary mode for reading */ | ||||||
|  |     File = fopen(FileName, "rb"); | ||||||
|  |     if(!File) { | ||||||
|  |         /* Failed to open file */ | ||||||
|  |         perror("Failed to open sector file for reading"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Read sectors to buffer */ | ||||||
|  |     if(fread(Buffer, 1, BytesToRead, File) != BytesToRead) | ||||||
|  |     { | ||||||
|  |         /* Failed to read sectors */ | ||||||
|  |         perror("Failed to read sectors from file"); | ||||||
|  |         fclose(File); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Close the file */ | ||||||
|  |     fclose(File); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Creates a directory in the image */ | ||||||
|  | static void MakeDirectory(const char *Image, long Offset, const char *Relative) | ||||||
|  | { | ||||||
|  |     char Command[4096]; | ||||||
|  |  | ||||||
|  |     /* Create the directory in the image */ | ||||||
|  |     snprintf(Command, sizeof(Command), "mmd -i \"%s@@%ld\" \"::/%s\"", Image, Offset, Relative); | ||||||
|  |     system(Command); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Main function */ | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  |     FILE *File; | ||||||
|  |     long Index; | ||||||
|  |     long FatFormat = 32; | ||||||
|  |     char FormatCommand[512]; | ||||||
|  |     long FormatPartition = 0; | ||||||
|  |     long DiskSizeBytes = 0; | ||||||
|  |     long DiskSizeMB = 0; | ||||||
|  |     long MergedSize = 0; | ||||||
|  |     long PreloaderSize = 0; | ||||||
|  |     long SectorsToWrite = 0; | ||||||
|  |     long VbrExtraSector = -1; | ||||||
|  |     long VbrFileSize = -1; | ||||||
|  |     long VbrTotalSectors = 0; | ||||||
|  |     long VbrLastSector = 99; | ||||||
|  |     char VbrInfo[128] = ""; | ||||||
|  |     MBR_PARTITION Partition = {0}; | ||||||
|  |     char Zero[SECTOR_SIZE] = {0}; | ||||||
|  |     uint8_t Mbr[SECTOR_SIZE] = {0}; | ||||||
|  |     uint8_t ImageVbr[SECTOR_SIZE * 2] = {0}; | ||||||
|  |     uint8_t *MergedData = NULL; | ||||||
|  |     uint8_t *PreloaderData = NULL; | ||||||
|  |     uint8_t *FullVbrData = NULL; | ||||||
|  |     const char *FileName = NULL; | ||||||
|  |     const char *MbrFile = NULL; | ||||||
|  |     const char *PreloadFile = NULL; | ||||||
|  |     const char *VbrFile = NULL; | ||||||
|  |     const char *CopyDir = NULL; | ||||||
|  |  | ||||||
|  |     /* Parse command line arguments */ | ||||||
|  |     for(Index = 1; Index < argc; Index++) | ||||||
|  |     { | ||||||
|  |         if(strcmp(argv[Index], "-c") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* Copy directory */ | ||||||
|  |             CopyDir = argv[++Index]; | ||||||
|  |         } | ||||||
|  |         else if(strcmp(argv[Index], "-e") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* VBR extra data sector */ | ||||||
|  |             VbrExtraSector = atol(argv[++Index]); | ||||||
|  |         } | ||||||
|  |         else if(strcmp(argv[Index], "-f") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* Format partition */ | ||||||
|  |             FormatPartition = 1; | ||||||
|  |             FatFormat = atoi(argv[++Index]); | ||||||
|  |             if(FatFormat != 16 && FatFormat != 32) | ||||||
|  |             { | ||||||
|  |                 fprintf(stderr, "Error: FAT format (-f) must be 16 or 32\n"); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else if(strcmp(argv[Index], "-m") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* MBR file */ | ||||||
|  |             MbrFile = argv[++Index]; | ||||||
|  |         } | ||||||
|  |         else if(strcmp(argv[Index], "-o") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* Output file */ | ||||||
|  |             FileName = argv[++Index]; | ||||||
|  |         } | ||||||
|  |         else if(strcmp(argv[Index], "-p") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* Preloader file */ | ||||||
|  |             PreloadFile = argv[++Index]; | ||||||
|  |         } | ||||||
|  |         else if(strcmp(argv[Index], "-s") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* Disk size */ | ||||||
|  |             DiskSizeMB = atol(argv[++Index]); | ||||||
|  |         } | ||||||
|  |         else if(strcmp(argv[Index], "-v") == 0 && Index + 1 < argc) | ||||||
|  |         { | ||||||
|  |             /* VBR file */ | ||||||
|  |             VbrFile = argv[++Index]; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             /* Unknown argument */ | ||||||
|  |             fprintf(stderr, "Unknown argument: %s\n", argv[Index]); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Check for required arguments */ | ||||||
|  |     if(DiskSizeMB <= 0 || FileName == NULL) | ||||||
|  |     { | ||||||
|  |         /* Missing required arguments, print usage */ | ||||||
|  |         fprintf(stderr, "Usage: %s -o <output.img> -s <size_MB> [-b <sector>] [-c <dir>] [-f 16|32] [-m <mbr.img>] [-p <preload.bin>] [-v <vbr.img>]\n", argv[0]); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Validate preload usage */ | ||||||
|  |     if(PreloadFile && !VbrFile) | ||||||
|  |     { | ||||||
|  |         /* Preloader code specified without VBR */ | ||||||
|  |         fprintf(stderr, "Error: Option -p (PRELOADER code) requires -v (VBR code) to be specified as well.\n"); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Calculate disk size in bytes */ | ||||||
|  |     DiskSizeBytes = DiskSizeMB * 1024 * 1024; | ||||||
|  |  | ||||||
|  |     /* Open the output file in binary mode */ | ||||||
|  |     File = fopen(FileName, "wb"); | ||||||
|  |     if(!File) { | ||||||
|  |         /* Failed to open file */ | ||||||
|  |         perror("Failed to open disk image file"); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Write zeros to the disk image file */ | ||||||
|  |     for(Index = 0; Index < DiskSizeBytes / SECTOR_SIZE; Index++) | ||||||
|  |     { | ||||||
|  |         if(fwrite(Zero, 1, SECTOR_SIZE, File) != SECTOR_SIZE) | ||||||
|  |         { | ||||||
|  |             /* Failed to write to disk image file */ | ||||||
|  |             perror("Failed to write to disk image file"); | ||||||
|  |             fclose(File); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Load MBR if provided */ | ||||||
|  |     if(MbrFile) | ||||||
|  |     { | ||||||
|  |         if(LoadSectors(MbrFile, Mbr, 1) != 0) | ||||||
|  |         { | ||||||
|  |             /* Failed to load MBR from file */ | ||||||
|  |             perror("Failed to load MBR from file"); | ||||||
|  |             fclose(File); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Setup MBR partition as W95 FAT16 or FAT32 */ | ||||||
|  |     Partition.BootFlag = 0x80; | ||||||
|  |     Partition.Type = (FatFormat == 16) ? 0x06 : 0x0B; | ||||||
|  |     Partition.StartLBA = 2048; | ||||||
|  |     Partition.Size = (DiskSizeBytes / SECTOR_SIZE) - Partition.StartLBA; | ||||||
|  |  | ||||||
|  |     /* Write MBR */ | ||||||
|  |     memcpy(&Mbr[446], &Partition, sizeof(MBR_PARTITION)); | ||||||
|  |     Mbr[510] = 0x55; | ||||||
|  |     Mbr[511] = 0xAA; | ||||||
|  |  | ||||||
|  |     /* Write the MBR to the beginning of the disk image */ | ||||||
|  |     fseek(File, 0, SEEK_SET); | ||||||
|  |     if(fwrite(Mbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE) | ||||||
|  |     { | ||||||
|  |         /* Failed to write MBR to disk image */ | ||||||
|  |         perror("Failed to write MBR to disk image"); | ||||||
|  |         fclose(File); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Check if we need to format the partition */ | ||||||
|  |     if(FormatPartition) | ||||||
|  |     { | ||||||
|  |         /* Close file before calling external formatter */ | ||||||
|  |         fclose(File); | ||||||
|  |  | ||||||
|  |         /* Build mformat command */ | ||||||
|  |         if(FatFormat == 16) | ||||||
|  |         { | ||||||
|  |             /* Format partition as FAT16 */ | ||||||
|  |             snprintf(FormatCommand, sizeof(FormatCommand), | ||||||
|  |                      "mformat -i %s@@%ld", | ||||||
|  |                      FileName, (long)(Partition.StartLBA * SECTOR_SIZE)); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             /* Format partition as FAT32 */ | ||||||
|  |             snprintf(FormatCommand, sizeof(FormatCommand), | ||||||
|  |                      "mformat -i %s@@%ld -F", | ||||||
|  |                      FileName, (long)(Partition.StartLBA * SECTOR_SIZE)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Format the partition */ | ||||||
|  |         if(system(FormatCommand) != 0) | ||||||
|  |         { | ||||||
|  |             /* Failed to format partition */ | ||||||
|  |             perror("Failed to format partition"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Reopen disk image */ | ||||||
|  |         File = fopen(FileName, "r+b"); | ||||||
|  |         if(!File) { | ||||||
|  |             /* Failed to open file */ | ||||||
|  |             perror("Failed to reopen disk image"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Read the VBR created by mformat */ | ||||||
|  |         fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET); | ||||||
|  |         if(fread(ImageVbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE) | ||||||
|  |         { | ||||||
|  |             /* Failed to read VBR */ | ||||||
|  |             perror("Failed to read VBR from disk image"); | ||||||
|  |             fclose(File); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Set the number of hidden sectors, as mformat sets it to 0 */ | ||||||
|  |         if(*(uint32_t*)&ImageVbr[0x1C] == 0) | ||||||
|  |         { | ||||||
|  |             memcpy(&ImageVbr[0x1C], &Partition.StartLBA, sizeof(uint32_t)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Check FAT format */ | ||||||
|  |         if(FatFormat == 32) | ||||||
|  |         { | ||||||
|  |             /* For FAT32, TotalSectors32 must be set */ | ||||||
|  |             *(uint16_t*)&ImageVbr[0x13] = 0; | ||||||
|  |             if(*(uint32_t*)&ImageVbr[0x20] == 0) | ||||||
|  |             { | ||||||
|  |                 /* Mformat did not set the field, update it */ | ||||||
|  |                 memcpy(&ImageVbr[0x20], &Partition.Size, sizeof(uint32_t)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             /* For FAT16, check if parition size exceeds 65535 sectors */ | ||||||
|  |             if(Partition.Size < 65536) | ||||||
|  |             { | ||||||
|  |                 /* Partition smaller than 32MB (65536 sectors), use 16-bit field TotalSectors16 */ | ||||||
|  |                 if(*(uint16_t*)&ImageVbr[0x13] == 0) | ||||||
|  |                 { | ||||||
|  |                     /* Mformat did not set the field, update it */ | ||||||
|  |                     memcpy(&ImageVbr[0x13], &((uint16_t){Partition.Size}), sizeof(uint16_t)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 /* Partition larger than 32MB (65536 sectors), use 32-bit field TotalSectors32 */ | ||||||
|  |                 *(uint16_t*)&ImageVbr[0x13] = 0; | ||||||
|  |                 if(*(uint32_t*)&ImageVbr[0x20] == 0) | ||||||
|  |                 { | ||||||
|  |                     /* Mformat did not set the field, update it */ | ||||||
|  |                     memcpy(&ImageVbr[0x20], &Partition.Size, sizeof(uint32_t)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Set DriveNumber to emulate hard disk */ | ||||||
|  |         ImageVbr[0x40] = 0x80; | ||||||
|  |  | ||||||
|  |         /* Write the corrected VBR back to the disk image */ | ||||||
|  |         fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET); | ||||||
|  |         if(fwrite(ImageVbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE) | ||||||
|  |         { | ||||||
|  |             /* Failed to write VBR */ | ||||||
|  |             perror("Failed to write VBR to disk image"); | ||||||
|  |             fclose(File); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Write VBR to the start of the partition, if provided */ | ||||||
|  |     if(VbrFile) | ||||||
|  |     { | ||||||
|  |         VbrFileSize = GetSectorFileSize(VbrFile); | ||||||
|  |         if(VbrFileSize < 0) | ||||||
|  |         { | ||||||
|  |             /* Unable to determine VBR file size */ | ||||||
|  |             perror("Could not get size of VBR file\n"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Check if VBR file size is a multiple of sector size */ | ||||||
|  |         if(VbrFileSize % SECTOR_SIZE != 0) | ||||||
|  |         { | ||||||
|  |             /* Unable to determine VBR file size */ | ||||||
|  |             perror("VBR file size is not a multiple of sector size\n"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Calculate number of VBR sectors */ | ||||||
|  |         VbrTotalSectors = VbrFileSize / SECTOR_SIZE; | ||||||
|  |  | ||||||
|  |         /* Allocate memory for the entire VBR file */ | ||||||
|  |         FullVbrData = malloc(VbrFileSize); | ||||||
|  |         if(!FullVbrData) | ||||||
|  |         { | ||||||
|  |             /* Memory allocation failed */ | ||||||
|  |             perror("Failed to allocate memory for VBR file\n"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Read the entire VBR file into the buffer */ | ||||||
|  |         if(LoadSectors(VbrFile, FullVbrData, VbrTotalSectors) != 0) | ||||||
|  |         { | ||||||
|  |             /* Failed to load VBR from file */ | ||||||
|  |             perror("Failed to load VBR from file\n"); | ||||||
|  |             free(FullVbrData); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Read the existing VBR from the formatted partition to get the correct BPB */ | ||||||
|  |         fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET); | ||||||
|  |         if(fread(ImageVbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE) | ||||||
|  |         { | ||||||
|  |             /* Failed to read VBR from disk image */ | ||||||
|  |             perror("Failed to read BPB from disk image\n"); | ||||||
|  |             free(FullVbrData); | ||||||
|  |             fclose(File); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Copy the BPB from the image's VBR to VBR buffer */ | ||||||
|  |         if(FatFormat == 32) | ||||||
|  |         { | ||||||
|  |             /* For FAT32, BPB is larger (up to offset 89) */ | ||||||
|  |             memcpy(&FullVbrData[3], &ImageVbr[3], 87); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             /* For FAT16, BPB is smaller (up to offset 61) */ | ||||||
|  |             memcpy(&FullVbrData[3], &ImageVbr[3], 59); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Write the first 512 bytes of the final, merged VBR to the start of the partition */ | ||||||
|  |         fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET); | ||||||
|  |         if(fwrite(FullVbrData, 1, SECTOR_SIZE, File) != SECTOR_SIZE) | ||||||
|  |         { | ||||||
|  |             /* Failed to write VBR to disk image */ | ||||||
|  |             perror("Failed to write VBR to disk image\n"); | ||||||
|  |             free(FullVbrData); | ||||||
|  |             fclose(File); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Handle extra VBR data if it exists */ | ||||||
|  |         if(FatFormat == 32) | ||||||
|  |         { | ||||||
|  |             /* Check if a preloader file was provided */ | ||||||
|  |             if(PreloadFile) | ||||||
|  |             { | ||||||
|  |                 /* Get the size of the preloader file */ | ||||||
|  |                 PreloaderSize = GetSectorFileSize(PreloadFile); | ||||||
|  |                 if(PreloaderSize < 0) | ||||||
|  |                 { | ||||||
|  |                     /* Unable to determine preloader file size */ | ||||||
|  |                     perror("Could not get size of preloader file.\n"); | ||||||
|  |                     free(FullVbrData); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Check if preloader size is multiple of 512 bytes */ | ||||||
|  |                 if(PreloaderSize % SECTOR_SIZE != 0) | ||||||
|  |                 { | ||||||
|  |                     /* Preloader file size is not a multiple of 512 bytes */ | ||||||
|  |                     perror("Preloader file size is not a multiple of sector size\n"); | ||||||
|  |                     free(FullVbrData); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Allocate buffer for preloader */ | ||||||
|  |                 PreloaderData = malloc((size_t)PreloaderSize); | ||||||
|  |                 if(!PreloaderData) | ||||||
|  |                 { | ||||||
|  |                     /* Memory allocation failed */ | ||||||
|  |                     perror("Failed to allocate memory for preloader"); | ||||||
|  |                     free(FullVbrData); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Load preloader data */ | ||||||
|  |                 if(LoadSectors(PreloadFile, PreloaderData, PreloaderSize / SECTOR_SIZE) != 0) | ||||||
|  |                 { | ||||||
|  |                     /* Failed to load preloader data */ | ||||||
|  |                     perror("Failed to load Preloader code from file\n"); | ||||||
|  |                     free(FullVbrData); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Allocate new buffer for the first 512 bytes of VBR and preloader */ | ||||||
|  |                 MergedSize = SECTOR_SIZE + PreloaderSize; | ||||||
|  |                 MergedData = malloc(MergedSize); | ||||||
|  |                 if(!MergedData) | ||||||
|  |                 { | ||||||
|  |                     /* Memory allocation failed */ | ||||||
|  |                     perror("Failed to allocate memory for Preloader file\n"); | ||||||
|  |                     free(PreloaderData); | ||||||
|  |                     free(FullVbrData); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Merge VBR and preloader data */ | ||||||
|  |                 memcpy(MergedData, FullVbrData, SECTOR_SIZE); | ||||||
|  |                 memcpy(MergedData + SECTOR_SIZE, PreloaderData, PreloaderSize); | ||||||
|  |  | ||||||
|  |                 /* Free old buffers and replace with merged data */ | ||||||
|  |                 free(FullVbrData); | ||||||
|  |                 free(PreloaderData); | ||||||
|  |                 FullVbrData = MergedData; | ||||||
|  |  | ||||||
|  |                 /* Update VBR sectors count */ | ||||||
|  |                 VbrTotalSectors = (MergedSize + SECTOR_SIZE - 1) / SECTOR_SIZE; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             /* Check if there is extra VBR data to write */ | ||||||
|  |             if(VbrTotalSectors > 1) | ||||||
|  |             { | ||||||
|  |                 /* Check if extra sector has been provided by the user */ | ||||||
|  |                 if(VbrExtraSector == -1) | ||||||
|  |                 { | ||||||
|  |                     /* Determine a safe sector to write extra VBR data to */ | ||||||
|  |                     long sectors_to_write = VbrTotalSectors - 1; | ||||||
|  |                     VbrExtraSector = DetermineExtraSector(sectors_to_write); | ||||||
|  |                     if(VbrExtraSector == -1) | ||||||
|  |                     { | ||||||
|  |                         /* Failed to find a safe sector */ | ||||||
|  |                         fprintf(stderr, "Error: Could not automatically find a safe space in the FAT32 reserved region for %ld extra VBR sectors.\n", | ||||||
|  |                                 sectors_to_write); | ||||||
|  |                         free(FullVbrData); | ||||||
|  |                         return 1; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Calculate number of sectors and last sector to write */ | ||||||
|  |                 SectorsToWrite = VbrTotalSectors - 1; | ||||||
|  |                 VbrLastSector = VbrExtraSector + SectorsToWrite - 1; | ||||||
|  |  | ||||||
|  |                 /* Ensure VBR will not be writen outside the reserved region (32 sectors for FAT32) */ | ||||||
|  |                 if(VbrLastSector >= 32) | ||||||
|  |                 { | ||||||
|  |                     /* The remaining space is not large enough to fit the extra VBR data */ | ||||||
|  |                     fprintf(stderr, "Error: VBR file is too large. Writing to sector %ld would exceed the FAT32 reserved region (32 sectors).\n", VbrLastSector); | ||||||
|  |                     free(FullVbrData); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Safety check: ensure we do not overwrite critical sectors */ | ||||||
|  |                 for(Index = 0; Fat32ReservedMap[Index].SectorNumber != -1; Index++) | ||||||
|  |                 { | ||||||
|  |                     /* Check if we are about to overwrite a critical sector */ | ||||||
|  |                     if(VbrExtraSector <= Fat32ReservedMap[Index].SectorNumber && VbrLastSector >= Fat32ReservedMap[Index].SectorNumber) | ||||||
|  |                     { | ||||||
|  |                         /* We are about to overwrite a critical sector */ | ||||||
|  |                         fprintf(stderr, "Error: Writing VBR extra data would overwrite critical sector %d (%s).\n", | ||||||
|  |                                 Fat32ReservedMap[Index].SectorNumber, Fat32ReservedMap[Index].Description); | ||||||
|  |                         free(FullVbrData); | ||||||
|  |                         return 1; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 /* Write the rest of the VBR data */ | ||||||
|  |                 fseek(File, (Partition.StartLBA + VbrExtraSector) * SECTOR_SIZE, SEEK_SET); | ||||||
|  |                 if(fwrite(FullVbrData + SECTOR_SIZE, 1, SectorsToWrite * SECTOR_SIZE, File) != (size_t)(SectorsToWrite * SECTOR_SIZE)) | ||||||
|  |                 { | ||||||
|  |                     /* Failed to write extra VBR data to disk image */ | ||||||
|  |                     perror("Failed to write extra VBR data to disk image"); | ||||||
|  |                     free(FullVbrData); | ||||||
|  |                     fclose(File); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else /* FatFormat == 16 */ | ||||||
|  |         { | ||||||
|  |             /* Check if there is extra VBR data to write */ | ||||||
|  |             if(VbrTotalSectors > 1 || PreloadFile) | ||||||
|  |             { | ||||||
|  |                 /* FAT16 only supports a 1-sector VBR */ | ||||||
|  |                 fprintf(stderr, "Error: FAT16 does not support multi-sector VBR or preloader data.\n"); | ||||||
|  |                 free(FullVbrData); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Free allocated memory */ | ||||||
|  |         free(FullVbrData); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Close file */ | ||||||
|  |     fclose(File); | ||||||
|  |  | ||||||
|  |     /* Copy files if requested */ | ||||||
|  |     if(CopyDir) | ||||||
|  |     { | ||||||
|  |         CopyData(FileName, (long)(Partition.StartLBA * SECTOR_SIZE), CopyDir, ""); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Check if VBR was written */ | ||||||
|  |     if(VbrFile) | ||||||
|  |     { | ||||||
|  |         /* Compose VBR info string */ | ||||||
|  |         if(VbrExtraSector != -1) | ||||||
|  |         { | ||||||
|  |             if(PreloadFile) | ||||||
|  |             { | ||||||
|  |                 /* Preloader written */ | ||||||
|  |                 snprintf(VbrInfo, sizeof(VbrInfo), ", VBR written (preloader at sector %ld)", VbrExtraSector); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 /* VBR with extra data */ | ||||||
|  |                 snprintf(VbrInfo, sizeof(VbrInfo), ", VBR written (extra data at sector %ld)", VbrExtraSector); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             /* Standard VBR */ | ||||||
|  |             snprintf(VbrInfo, sizeof(VbrInfo), ", VBR written"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Print success message */ | ||||||
|  |     printf("Successfully created disk image '%s' (%ld MB) with bootable W95 FAT-%ld partition%s%s%s.\n", | ||||||
|  |            FileName, | ||||||
|  |            DiskSizeMB, | ||||||
|  |            FatFormat, | ||||||
|  |            MbrFile ? ", MBR written" : "", | ||||||
|  |            VbrInfo, | ||||||
|  |            CopyDir ? ", files copied" : ""); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										100
									
								
								tools/exetool.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								tools/exetool.c
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | |||||||
|  * PROJECT:     XTchain |  * PROJECT:     XTchain | ||||||
|  * LICENSE:     See COPYING.md in the top level directory |  * LICENSE:     See COPYING.md in the top level directory | ||||||
|  * FILE:        tools/exetool.c |  * FILE:        tools/exetool.c | ||||||
|  * DESCRIPTION: Portable Executable (PE) utility for changing subsystem |  * DESCRIPTION: Portable Executable (PE) utility for changing its signature and subsystem | ||||||
|  * DEVELOPERS:  Rafal Kupiec <belliash@codingworkshop.eu.org> |  * DEVELOPERS:  Rafal Kupiec <belliash@codingworkshop.eu.org> | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @@ -91,6 +91,7 @@ int main(int argc, char *argv[]) | |||||||
|     FILE *ExeFile; |     FILE *ExeFile; | ||||||
|     unsigned char Signature[4]; |     unsigned char Signature[4]; | ||||||
|     unsigned int HeaderOffset; |     unsigned int HeaderOffset; | ||||||
|  |     unsigned int ImageSignature; | ||||||
|     unsigned short SubSystem; |     unsigned short SubSystem; | ||||||
|     PPE_SUBSYSTEM NewSubSystem; |     PPE_SUBSYSTEM NewSubSystem; | ||||||
|  |  | ||||||
| @@ -101,44 +102,6 @@ int main(int argc, char *argv[]) | |||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Open the EXE file in binary mode */ |  | ||||||
|     ExeFile = fopen(argv[1], "r+b"); |  | ||||||
|     if(ExeFile == NULL) |  | ||||||
|     { |  | ||||||
|         /* Failed to open PE file */ |  | ||||||
|         printf("ERROR: Unable to open file %s\n", argv[1]); |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     /* Verify that the input file has a valid DOS header */ |  | ||||||
|     fread(Signature, sizeof(unsigned char), 4, ExeFile); |  | ||||||
|     if(Signature[0] != 'M' || Signature[1] != 'Z') |  | ||||||
|     { |  | ||||||
|         /* Invalid DOS header */ |  | ||||||
|         printf("ERROR: %s is not a valid EXE file\n", argv[1]); |  | ||||||
|         fclose(ExeFile); |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Verify that the input file has a valid PE header */ |  | ||||||
|     fseek(ExeFile, 0x3C, SEEK_SET); |  | ||||||
|     fread(&HeaderOffset, sizeof(unsigned int), 1, ExeFile); |  | ||||||
|     fseek(ExeFile, HeaderOffset, SEEK_SET); |  | ||||||
|     fread(Signature, sizeof(unsigned char), 4, ExeFile); |  | ||||||
|     if(Signature[0] != 'P' || Signature[1] != 'E' || Signature[2] != 0 || Signature[3] != 0) |  | ||||||
|     { |  | ||||||
|         /* Invalid PE header */ |  | ||||||
|         printf("Error: %s is not a valid PE file\n", argv[1]); |  | ||||||
|         fclose(ExeFile); |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Seek to the offset of the SubSystem field in the optional header */ |  | ||||||
|     fseek(ExeFile, HeaderOffset + 0x5C, SEEK_SET); |  | ||||||
|  |  | ||||||
|     /* Read the current SubSystem value */ |  | ||||||
|     fread(&SubSystem, sizeof(unsigned short), 1, ExeFile); |  | ||||||
|  |  | ||||||
|     /* Parse the new SubSystem value from the command line argument */ |     /* Parse the new SubSystem value from the command line argument */ | ||||||
|     NewSubSystem = getSubSystem(argv[2]); |     NewSubSystem = getSubSystem(argv[2]); | ||||||
|     if(NewSubSystem->Identifier == 0) |     if(NewSubSystem->Identifier == 0) | ||||||
| @@ -148,10 +111,63 @@ int main(int argc, char *argv[]) | |||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Print new SubSystem identifier */ |     /* Open the EXE file in binary mode */ | ||||||
|  |     ExeFile = fopen(argv[1], "r+b"); | ||||||
|  |     if(ExeFile == NULL) | ||||||
|  |     { | ||||||
|  |         /* Failed to open PE file */ | ||||||
|  |         printf("ERROR: Unable to open file %s\n", argv[1]); | ||||||
|  |         return 2; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /* Verify that the input file has a valid DOS header */ | ||||||
|  |     fread(Signature, sizeof(unsigned char), 4, ExeFile); | ||||||
|  |     if(Signature[0] != 'M' || Signature[1] != 'Z') | ||||||
|  |     { | ||||||
|  |         /* Invalid DOS header */ | ||||||
|  |         printf("ERROR: %s is not a valid EXE file\n", argv[1]); | ||||||
|  |         fclose(ExeFile); | ||||||
|  |         return 3; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Verify that the input file has a valid PE header */ | ||||||
|  |     fseek(ExeFile, 0x3C, SEEK_SET); | ||||||
|  |     fread(&HeaderOffset, sizeof(unsigned int), 1, ExeFile); | ||||||
|  |     fseek(ExeFile, HeaderOffset, SEEK_SET); | ||||||
|  |     fread(Signature, sizeof(unsigned char), 4, ExeFile); | ||||||
|  |     if((Signature[0] != 'P' || Signature[1] != 'E' || Signature[2] != 0 || Signature[3] != 0) && | ||||||
|  |        (Signature[0] != 'P' || Signature[1] != 'E' || Signature[2] != 'X' || Signature[3] != 'T')) | ||||||
|  |     { | ||||||
|  |         /* Invalid PE header */ | ||||||
|  |         printf("Error: %s is not a valid PE file\n", argv[1]); | ||||||
|  |         fclose(ExeFile); | ||||||
|  |         return 3; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Check if setting XT subsystem */ | ||||||
|  |     if(NewSubSystem->Identifier >= 0x14 && NewSubSystem->Identifier <= 0x19) | ||||||
|  |     { | ||||||
|  |         /* Write PEXT signature */ | ||||||
|  |         ImageSignature = 0x54584550; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         /* Write PE00 signature */ | ||||||
|  |         ImageSignature = 0x00004550; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Seek back to header offset and write new signature */ | ||||||
|  |     fseek(ExeFile, HeaderOffset, SEEK_SET); | ||||||
|  |     fwrite(&ImageSignature, sizeof(ImageSignature), 1, ExeFile); | ||||||
|  |  | ||||||
|  |     /* Seek to the offset of the SubSystem field in the optional header */ | ||||||
|  |     fseek(ExeFile, HeaderOffset + 0x5C, SEEK_SET); | ||||||
|  |  | ||||||
|  |     /* Read the current SubSystem value */ | ||||||
|  |     fread(&SubSystem, sizeof(unsigned short), 1, ExeFile); | ||||||
|  |  | ||||||
|     /* Seek back to the SubSystem field in the optional header */ |     /* Seek back to the SubSystem field in the optional header */ | ||||||
|     fseek(ExeFile, -sizeof(unsigned short), SEEK_CUR); |     fseek(ExeFile, -(long)sizeof(unsigned short), SEEK_CUR); | ||||||
|  |  | ||||||
|     /* Write the new SubSystem value */ |     /* Write the new SubSystem value */ | ||||||
|     fwrite(&NewSubSystem->Identifier, sizeof(unsigned short), 1, ExeFile); |     fwrite(&NewSubSystem->Identifier, sizeof(unsigned short), 1, ExeFile); | ||||||
| @@ -160,7 +176,7 @@ int main(int argc, char *argv[]) | |||||||
|     fclose(ExeFile); |     fclose(ExeFile); | ||||||
|  |  | ||||||
|     /* Finished successfully */ |     /* Finished successfully */ | ||||||
|     printf("PE SubSystem modified: 0x%04X <%s> to 0x%04X <%s>\n", |     printf("PE SubSystem modified: 0x%02X <%s> to 0x%02X <%s>\n", | ||||||
|            SubSystem, getSubSystemName(SubSystem), NewSubSystem->Identifier, NewSubSystem->Name); |            SubSystem, getSubSystemName(SubSystem), NewSubSystem->Identifier, NewSubSystem->Name); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										558
									
								
								tools/windres.c
									
									
									
									
									
								
							
							
						
						
									
										558
									
								
								tools/windres.c
									
									
									
									
									
								
							| @@ -1,558 +0,0 @@ | |||||||
| /** |  | ||||||
|  * PROJECT:     XTchain |  | ||||||
|  * LICENSE:     See COPYING.md in the top level directory |  | ||||||
|  * FILE:        tools/windres.c |  | ||||||
|  * DESCRIPTION: WINDRES compatible interface to LLVM |  | ||||||
|  * DEVELOPERS:  Josh de Kock <josh@itanimul.li> |  | ||||||
|  *              Martin Storsjo <martin@martin.st> |  | ||||||
|  *              Rafal Kupiec <belliash@codingworkshop.eu.org> |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "xtchain.h" |  | ||||||
|  |  | ||||||
| #define WINDRES_VERSION "1.0" |  | ||||||
|  |  | ||||||
| #ifndef DEFAULT_TARGET |  | ||||||
| #define DEFAULT_TARGET "x86_64-w64-mingw32" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include <stdarg.h> |  | ||||||
|  |  | ||||||
| #define _tspawnvp_escape _spawnvp |  | ||||||
|  |  | ||||||
| #include <sys/wait.h> |  | ||||||
| #include <errno.h> |  | ||||||
|  |  | ||||||
| #define _P_WAIT 0 |  | ||||||
|  |  | ||||||
| static |  | ||||||
| int |  | ||||||
| _spawnvp(int mode, |  | ||||||
|          const char *filename, |  | ||||||
|          const char * const *argv) |  | ||||||
| { |  | ||||||
|     pid_t pid; |  | ||||||
|  |  | ||||||
|     if(!(pid = fork())) |  | ||||||
|     { |  | ||||||
|         execvp(filename, (char **) argv); |  | ||||||
|         perror(filename); |  | ||||||
|         exit(1); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     int stat = 0; |  | ||||||
|  |  | ||||||
|     if(waitpid(pid, &stat, 0) == -1) |  | ||||||
|     { |  | ||||||
|         return -1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if(WIFEXITED(stat)) |  | ||||||
|     { |  | ||||||
|         return WEXITSTATUS(stat); |  | ||||||
|     } |  | ||||||
|     errno = EIO; |  | ||||||
|  |  | ||||||
|     return -1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static |  | ||||||
| const |  | ||||||
| char *unescape_cpp(const char *str) |  | ||||||
| { |  | ||||||
|     char *out = strdup(str); |  | ||||||
|     int len = strlen(str); |  | ||||||
|     int i, outpos = 0; |  | ||||||
|  |  | ||||||
|     for(i = 0; i < len - 1; i++) |  | ||||||
|     { |  | ||||||
|         if(str[i] == '\\' && str[i + 1] == '"') |  | ||||||
|         { |  | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|         out[outpos++] = str[i]; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     while(i < len) |  | ||||||
|     { |  | ||||||
|         out[outpos++] = str[i++]; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     out[outpos++] = '\0'; |  | ||||||
|  |  | ||||||
|     return out; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static |  | ||||||
| void print_version(void) |  | ||||||
| { |  | ||||||
|     printf("XTchain windres (GNU windres compatible) %s\n", WINDRES_VERSION); |  | ||||||
|     exit(0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static |  | ||||||
| void print_help(void) |  | ||||||
| { |  | ||||||
|     printf( |  | ||||||
|     "usage: llvm-windres <OPTION> [INPUT-FILE] [OUTPUT-FILE]\n" |  | ||||||
|     "\n" |  | ||||||
|     "LLVM Tool to manipulate Windows resources with a GNU windres interface.\n" |  | ||||||
|     "\n" |  | ||||||
|     "Options:\n" |  | ||||||
|     "  -i, --input <arg>          Name of the input file.\n" |  | ||||||
|     "  -o, --output <arg>         Name of the output file.\n" |  | ||||||
|     "  -J, --input-format <arg>   Input format to read.\n" |  | ||||||
|     "  -O, --output-format <arg>  Output format to generate.\n" |  | ||||||
|     "  --preprocessor <arg>       Custom preprocessor command.\n" |  | ||||||
|     "  --preprocessor-arg <arg>   Preprocessor command arguments.\n" |  | ||||||
|     "  -F, --target <arg>         Target for COFF objects to be compiled for.\n" |  | ||||||
|     "  -I, --include-dir <arg>    Include directory to pass to preprocessor and resource compiler.\n" |  | ||||||
|     "  -D, --define <arg[=val]>   Define to pass to preprocessor.\n" |  | ||||||
|     "  -U, --undefine <arg[=val]> Undefine to pass to preprocessor.\n" |  | ||||||
|     "  -c, --codepage <arg>       Default codepage to use when reading an rc file (0x0-0xffff).\n" |  | ||||||
|     "  -l, --language <arg>       Specify default language (0x0-0xffff).\n" |  | ||||||
|     "      --use-temp-file        Use a temporary file for the preprocessing output.\n" |  | ||||||
|     "  -v, --verbose              Enable verbose output.\n" |  | ||||||
|     "  -V, --version              Display version.\n" |  | ||||||
|     "  -h, --help                 Display this message and exit.\n" |  | ||||||
|     "Input Formats:\n" |  | ||||||
|     "  rc                         Text Windows Resource\n" |  | ||||||
|     "  res                        Binary Windows Resource\n" |  | ||||||
|     "Output Formats:\n" |  | ||||||
|     "  res                        Binary Windows Resource\n" |  | ||||||
|     "  coff                       COFF object\n" |  | ||||||
|     "Targets:\n" |  | ||||||
|     "  pe-x86-64\n" |  | ||||||
|     "  pei-x86-64\n" |  | ||||||
|     "  pe-i386\n" |  | ||||||
|     "  pei-i386\n"); |  | ||||||
|     exit(0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static |  | ||||||
| void error(const char *basename, |  | ||||||
|            const char *fmt, |  | ||||||
|            ...) |  | ||||||
| { |  | ||||||
|     fprintf(stderr, _T(TS": error: "), basename); |  | ||||||
|     va_list ap; |  | ||||||
|     va_start(ap, fmt); |  | ||||||
|     vfprintf(stderr, fmt, ap); |  | ||||||
|     fprintf(stderr, _T("\n")); |  | ||||||
|     va_end(ap); |  | ||||||
|     exit(1); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static |  | ||||||
| void print_argv(const char **exec_argv) |  | ||||||
| { |  | ||||||
|     while(*exec_argv) |  | ||||||
|     { |  | ||||||
|         fprintf(stderr, _T(TS" "), *exec_argv); |  | ||||||
|         exec_argv++; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fprintf(stderr, _T("\n")); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static |  | ||||||
| void check_num_args(int arg, |  | ||||||
|                     int max_arg) |  | ||||||
| { |  | ||||||
|     if(arg > max_arg) |  | ||||||
|     { |  | ||||||
|         fprintf(stderr, "Too many options added\n"); |  | ||||||
|         abort(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int main(int argc, |  | ||||||
|          char* argv[]) |  | ||||||
| { |  | ||||||
|     const char *dir; |  | ||||||
|     const char *basename; |  | ||||||
|     const char *target; |  | ||||||
|  |  | ||||||
|     split_argv(argv[0], &dir, &basename, &target, NULL); |  | ||||||
|  |  | ||||||
|     if (!target) |  | ||||||
|         target = _T(DEFAULT_TARGET); |  | ||||||
|  |  | ||||||
|     const char *bfd_target = NULL; |  | ||||||
|     const char *input = _T("-"); |  | ||||||
|     const char *output = _T("/dev/stdout"); |  | ||||||
|     const char *input_format = _T("rc"); |  | ||||||
|     const char *output_format = _T("coff"); |  | ||||||
|     const char **includes = malloc(argc * sizeof(*includes)); |  | ||||||
|     int nb_includes = 0; |  | ||||||
|     const char *codepage = _T("1252"); |  | ||||||
|     const char *language = NULL; |  | ||||||
|     const char **cpp_options = malloc(argc * sizeof(*cpp_options)); |  | ||||||
|     int nb_cpp_options = 0; |  | ||||||
|     int verbose = 0; |  | ||||||
|  |  | ||||||
| #define _tcslen_const(a) (sizeof(a)/sizeof(char) - 1) |  | ||||||
|  |  | ||||||
| #define _tcsstart(a, b) !strncmp(a, b, _tcslen_const(b)) |  | ||||||
|  |  | ||||||
| #define IF_MATCH_EITHER(short, long) \ |  | ||||||
|     if(!strcmp(argv[i], _T(short)) || !strcmp(argv[i], _T(long))) |  | ||||||
|  |  | ||||||
| #define IF_MATCH_THREE(first, second, third) \ |  | ||||||
|     if(!strcmp(argv[i], _T(first)) || !strcmp(argv[i], _T(second)) || !strcmp(argv[i], _T(third))) |  | ||||||
|  |  | ||||||
| #define OPTION(short, long, var) \ |  | ||||||
|     if(_tcsstart(argv[i], _T(short)) && argv[i][_tcslen_const(_T(short))]) { \ |  | ||||||
|         var = argv[i] + _tcslen_const(_T(short)); \ |  | ||||||
|     } else if(_tcsstart(argv[i], _T(long "="))) { \ |  | ||||||
|         var = strchr(argv[i], '=') + 1; \ |  | ||||||
|     } else IF_MATCH_EITHER(short, long) { \ |  | ||||||
|         if(i + 1 < argc) \ |  | ||||||
|             var = argv[++i]; \ |  | ||||||
|         else \ |  | ||||||
|             error(basename, _T(TS" missing argument"), argv[i]); \ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| #define SEPARATE_ARG(var) do { \ |  | ||||||
|         if(i + 1 < argc) \ |  | ||||||
|             var = argv[++i]; \ |  | ||||||
|         else \ |  | ||||||
|             error(basename, _T(TS" missing argument"), argv[i]); \ |  | ||||||
|     } while (0) |  | ||||||
|  |  | ||||||
| #define SEPARATE_ARG_PREFIX(var, prefix) do { \ |  | ||||||
|         if(i + 1 < argc) \ |  | ||||||
|             var = concat(_T(prefix), argv[++i]); \ |  | ||||||
|         else \ |  | ||||||
|             error(basename, _T(TS" missing argument"), argv[i]); \ |  | ||||||
|     } while (0) |  | ||||||
|  |  | ||||||
|     for(int i = 1; i < argc; i++) |  | ||||||
|     { |  | ||||||
|         OPTION("-i", "--input", input) |  | ||||||
|         else OPTION("-o", "--output", output) |  | ||||||
|         else OPTION("-J", "--input-format", input_format) |  | ||||||
|         else OPTION("-O", "--output-format", output_format) |  | ||||||
|         else OPTION("-F", "--target", bfd_target) |  | ||||||
|         else IF_MATCH_THREE("-I", "--include-dir", "--include") { |  | ||||||
|             SEPARATE_ARG(includes[nb_includes++]); |  | ||||||
|         } |  | ||||||
|         else if(_tcsstart(argv[i], _T("--include-dir=")) || |  | ||||||
|                 _tcsstart(argv[i], _T("--include="))) |  | ||||||
|         { |  | ||||||
|             includes[nb_includes++] = strchr(argv[i], '=') + 1; |  | ||||||
|         } |  | ||||||
|         else if(_tcsstart(argv[i], _T("-I"))) |  | ||||||
|         { |  | ||||||
|             includes[nb_includes++] = argv[i] + 2; |  | ||||||
|         } |  | ||||||
|         else OPTION("-c", "--codepage", codepage) |  | ||||||
|         else OPTION("-l", "--language", language) |  | ||||||
|         else if(!strcmp(argv[i], _T("--preprocessor"))) |  | ||||||
|         { |  | ||||||
|             error(basename, _T("ENOSYS")); |  | ||||||
|         } |  | ||||||
|         else if(_tcsstart(argv[i], _T("--preprocessor-arg="))) |  | ||||||
|         { |  | ||||||
|             cpp_options[nb_cpp_options++] = strchr(argv[i], '=') + 1; |  | ||||||
|         } |  | ||||||
|         else if(!strcmp(argv[i], _T("--preprocessor-arg"))) |  | ||||||
|         { |  | ||||||
|             SEPARATE_ARG(cpp_options[nb_cpp_options++]); |  | ||||||
|         } |  | ||||||
|         else IF_MATCH_EITHER("-D", "--define") |  | ||||||
|         { |  | ||||||
|             SEPARATE_ARG_PREFIX(cpp_options[nb_cpp_options++], "-D"); |  | ||||||
|         } |  | ||||||
|         else if(_tcsstart(argv[i], _T("-D"))) |  | ||||||
|         { |  | ||||||
|             cpp_options[nb_cpp_options++] = argv[i]; |  | ||||||
|         } |  | ||||||
|         else IF_MATCH_EITHER("-U", "--undefine") |  | ||||||
|         { |  | ||||||
|             SEPARATE_ARG_PREFIX(cpp_options[nb_cpp_options++], "-U"); |  | ||||||
|         } |  | ||||||
|         else if(_tcsstart(argv[i], _T("-U"))) |  | ||||||
|         { |  | ||||||
|             cpp_options[nb_cpp_options++] = argv[i]; |  | ||||||
|         } |  | ||||||
|         else IF_MATCH_EITHER("-v", "--verbose") |  | ||||||
|         { |  | ||||||
|             verbose = 1; |  | ||||||
|         } |  | ||||||
|         else IF_MATCH_EITHER("-V", "--version") |  | ||||||
|         { |  | ||||||
|             print_version(); |  | ||||||
|         } |  | ||||||
|         else IF_MATCH_EITHER("-h", "--help") |  | ||||||
|         { |  | ||||||
|             print_help(); |  | ||||||
|         } |  | ||||||
|         else if(!strcmp(argv[i], _T("--use-temp-file"))) |  | ||||||
|         { |  | ||||||
|             // No-op, we use a temp file by default. |  | ||||||
|         } |  | ||||||
|         else if(_tcsstart(argv[i], _T("-"))) |  | ||||||
|         { |  | ||||||
|             error(basename, _T("unrecognized option: `"TS"'"), argv[i]); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             if(!strcmp(input, _T("-"))) |  | ||||||
|             { |  | ||||||
|                 input = argv[i]; |  | ||||||
|             } |  | ||||||
|             else if(!strcmp(output, _T("/dev/stdout"))) |  | ||||||
|             { |  | ||||||
|                 output = argv[i]; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 error(basename, _T("rip: `"TS"'"), argv[i]); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if(bfd_target) |  | ||||||
|     { |  | ||||||
|         if(!strcmp(bfd_target, _T("pe-x86-64")) || |  | ||||||
|            !strcmp(bfd_target, _T("pei-x86-64"))) |  | ||||||
|         { |  | ||||||
|            target = _T("x86_64-w64-mingw32"); |  | ||||||
|         } |  | ||||||
|         else if(!strcmp(bfd_target, _T("pe-i386")) || |  | ||||||
|                 !strcmp(bfd_target, _T("pei-i386"))) |  | ||||||
|         { |  | ||||||
|             target = _T("i686-w64-mingw32"); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             error(basename, _T("unsupported target: `"TS"'"), bfd_target); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     char *arch = strdup(target); |  | ||||||
|     char *dash = strchr(arch, '-'); |  | ||||||
|     if(dash) |  | ||||||
|     { |  | ||||||
|         *dash = '\0'; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const char *machine = _T("unknown"); |  | ||||||
|  |  | ||||||
|     if(!strcmp(arch, _T("i686"))) |  | ||||||
|     { |  | ||||||
|         machine = _T("X86"); |  | ||||||
|     } |  | ||||||
|     else if(!strcmp(arch, _T("x86_64"))) |  | ||||||
|     { |  | ||||||
|         machine = _T("X64"); |  | ||||||
|     } |  | ||||||
|     else if(!strcmp(arch, _T("armv7"))) |  | ||||||
|     { |  | ||||||
|         machine = _T("ARM"); |  | ||||||
|     } |  | ||||||
|     else if(!strcmp(arch, _T("aarch64"))) |  | ||||||
|     { |  | ||||||
|         machine = _T("ARM64"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const char *CC = concat(target, _T("-clang")); |  | ||||||
|     const char **rc_options = malloc(2 * argc * sizeof(*cpp_options)); |  | ||||||
|     int nb_rc_options = 0; |  | ||||||
|  |  | ||||||
|     for(int i = 0; i < nb_includes; i++) |  | ||||||
|     { |  | ||||||
|         cpp_options[nb_cpp_options++] = concat(_T("-I"), includes[i]); |  | ||||||
|         rc_options[nb_rc_options++] = _T("-I"); |  | ||||||
|         rc_options[nb_rc_options++] = includes[i]; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     for(int i = 0; i < nb_cpp_options; i++) |  | ||||||
|     { |  | ||||||
|         cpp_options[i] = unescape_cpp(cpp_options[i]); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const char *preproc_rc = concat(output, _T(".preproc.rc")); |  | ||||||
|     const char *res = concat(output, _T(".out.res")); |  | ||||||
|  |  | ||||||
|     char *inputdir = strdup(input); |  | ||||||
|     { |  | ||||||
|         char *sep = _tcsrchrs(inputdir, '/', '\\'); |  | ||||||
|         if(sep) |  | ||||||
|         { |  | ||||||
|             *sep = '\0'; |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             inputdir = strdup(_T(".")); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     int max_arg = 2 * argc + 20; |  | ||||||
|     const char **exec_argv = malloc((max_arg + 1) * sizeof(*exec_argv)); |  | ||||||
|     int arg = 0; |  | ||||||
|  |  | ||||||
|     if(!_tcsicmp(input_format, _T("rc"))) |  | ||||||
|     { |  | ||||||
|         exec_argv[arg++] = concat(dir, CC); |  | ||||||
|         exec_argv[arg++] = _T("-E"); |  | ||||||
|  |  | ||||||
|         for(int i = 0; i < nb_cpp_options; i++) |  | ||||||
|         { |  | ||||||
|             exec_argv[arg++] = cpp_options[i]; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         exec_argv[arg++] = _T("-xc"); |  | ||||||
|         exec_argv[arg++] = _T("-DRC_INVOKED=1"); |  | ||||||
|         exec_argv[arg++] = input; |  | ||||||
|         exec_argv[arg++] = _T("-o"); |  | ||||||
|         exec_argv[arg++] = preproc_rc; |  | ||||||
|         exec_argv[arg] = NULL; |  | ||||||
|  |  | ||||||
|         check_num_args(arg, max_arg); |  | ||||||
|  |  | ||||||
|         if(verbose) |  | ||||||
|         { |  | ||||||
|             print_argv(exec_argv); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         int ret = _tspawnvp_escape(_P_WAIT, exec_argv[0], exec_argv); |  | ||||||
|  |  | ||||||
|         if(ret == -1) |  | ||||||
|         { |  | ||||||
|             perror(exec_argv[0]); |  | ||||||
|             return 1; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(ret != 0) |  | ||||||
|         { |  | ||||||
|             error(basename, _T("preprocessor failed")); |  | ||||||
|             return ret; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         arg = 0; |  | ||||||
|         exec_argv[arg++] = concat(dir, _T("llvm-rc")); |  | ||||||
|  |  | ||||||
|         for(int i = 0; i < nb_rc_options; i++) |  | ||||||
|         { |  | ||||||
|             exec_argv[arg++] = rc_options[i]; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         exec_argv[arg++] = _T("-I"); |  | ||||||
|         exec_argv[arg++] = inputdir; |  | ||||||
|         exec_argv[arg++] = preproc_rc; |  | ||||||
|         exec_argv[arg++] = _T("-c"); |  | ||||||
|         exec_argv[arg++] = codepage; |  | ||||||
|  |  | ||||||
|         if(language) |  | ||||||
|         { |  | ||||||
|             exec_argv[arg++] = _T("-l"); |  | ||||||
|             exec_argv[arg++] = language; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         exec_argv[arg++] = _T("-fo"); |  | ||||||
|  |  | ||||||
|         if(!_tcsicmp(output_format, _T("res"))) |  | ||||||
|         { |  | ||||||
|             exec_argv[arg++] = output; |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             exec_argv[arg++] = res; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         exec_argv[arg] = NULL; |  | ||||||
|         check_num_args(arg, max_arg); |  | ||||||
|  |  | ||||||
|         if(verbose) |  | ||||||
|         { |  | ||||||
|             print_argv(exec_argv); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         ret = _tspawnvp_escape(_P_WAIT, exec_argv[0], exec_argv); |  | ||||||
|  |  | ||||||
|         if(ret == -1) |  | ||||||
|         { |  | ||||||
|             perror(exec_argv[0]); |  | ||||||
|             return 1; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(ret != 0) |  | ||||||
|         { |  | ||||||
|             error(basename, _T("llvm-rc failed")); |  | ||||||
|             if(!verbose) |  | ||||||
|             { |  | ||||||
|                 unlink(preproc_rc); |  | ||||||
|             } |  | ||||||
|             return ret; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(!_tcsicmp(output_format, _T("res"))) |  | ||||||
|         { |  | ||||||
|             // All done |  | ||||||
|         } |  | ||||||
|         else if(!_tcsicmp(output_format, _T("coff"))) |  | ||||||
|         { |  | ||||||
|             arg = 0; |  | ||||||
|             exec_argv[arg++] = concat(dir, _T("llvm-cvtres")); |  | ||||||
|             exec_argv[arg++] = res; |  | ||||||
|             exec_argv[arg++] = concat(_T("-machine:"), machine); |  | ||||||
|             exec_argv[arg++] = concat(_T("-out:"), output); |  | ||||||
|             exec_argv[arg] = NULL; |  | ||||||
|  |  | ||||||
|             check_num_args(arg, max_arg); |  | ||||||
|             if(verbose) |  | ||||||
|             { |  | ||||||
|                 print_argv(exec_argv); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             int ret = _tspawnvp_escape(_P_WAIT, exec_argv[0], exec_argv); |  | ||||||
|             if(ret == -1) |  | ||||||
|             { |  | ||||||
|                 perror(exec_argv[0]); |  | ||||||
|                 return 1; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if(!verbose) |  | ||||||
|             { |  | ||||||
|                 unlink(preproc_rc); |  | ||||||
|                 unlink(res); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return ret; |  | ||||||
|         } else { |  | ||||||
|             error(basename, _T("invalid output format: `"TS"'"), output_format); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     else if(!_tcsicmp(input_format, _T("res"))) |  | ||||||
|     { |  | ||||||
|         exec_argv[arg++] = concat(dir, _T("llvm-cvtres")); |  | ||||||
|         exec_argv[arg++] = input; |  | ||||||
|         exec_argv[arg++] = concat(_T("-machine:"), machine); |  | ||||||
|         exec_argv[arg++] = concat(_T("-out:"), output); |  | ||||||
|         exec_argv[arg] = NULL; |  | ||||||
|  |  | ||||||
|         check_num_args(arg, max_arg); |  | ||||||
|  |  | ||||||
|         if(verbose) |  | ||||||
|         { |  | ||||||
|             print_argv(exec_argv); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         int ret = _tspawnvp_escape(_P_WAIT, exec_argv[0], exec_argv); |  | ||||||
|         if(ret == -1) |  | ||||||
|         { |  | ||||||
|             perror(exec_argv[0]); |  | ||||||
|             return 1; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return ret; |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         error(basename, _T("invalid input format: `"TS"'"), input_format); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| @@ -7,56 +7,40 @@ | |||||||
|  *              Rafal Kupiec <belliash@codingworkshop.eu.org> |  *              Rafal Kupiec <belliash@codingworkshop.eu.org> | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifdef UNICODE | #include <dirent.h> | ||||||
| #define _UNICODE |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include <ctype.h> |  | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <stdint.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  |  | ||||||
| #define _T(x) x |  | ||||||
|  |  | ||||||
| #ifdef _UNICODE | #ifdef _WIN32 | ||||||
| #define TS "%ls" | #include <windows.h> | ||||||
|  | #define PATH_SEP '\\' | ||||||
| #else | #else | ||||||
| #define TS "%s" | #define PATH_SEP '/' | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| static | #define SECTOR_SIZE     512 | ||||||
| inline | #define _T(x)           x | ||||||
| int |  | ||||||
| _tcsicmp(const char *a, | typedef struct MBR_PARTITION { | ||||||
|          const char *b) |     uint8_t BootFlag;       // 0x80 = bootable, 0x00 = non-boot | ||||||
|  |     uint8_t StartCHS [3];   // CHS address | ||||||
|  |     uint8_t Type;           // Partition type | ||||||
|  |     uint8_t EndCHS[3];      // CHS address | ||||||
|  |     uint32_t StartLBA;      // Start sector | ||||||
|  |     uint32_t Size;          // Sectors count | ||||||
|  | } MBR_PARTITION, *PMBR_PARTITION; | ||||||
|  |  | ||||||
|  | typedef struct _RESERVED_SECTOR_INFO | ||||||
| { | { | ||||||
|     while(*a && tolower(*a) == tolower(*b)) |     int SectorNumber; | ||||||
|     { |     const char* Description; | ||||||
|         a++; | } RESERVED_SECTOR_INFO, *PRESERVED_SECTOR_INFO; | ||||||
|         b++; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return *a - *b; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static |  | ||||||
| inline |  | ||||||
| char * |  | ||||||
| concat(const char *prefix, |  | ||||||
|        const char *suffix) |  | ||||||
| { |  | ||||||
|     int prefixlen = strlen(prefix); |  | ||||||
|     int suffixlen = strlen(suffix); |  | ||||||
|  |  | ||||||
|     char *buf = malloc((prefixlen + suffixlen + 1) * sizeof(*buf)); |  | ||||||
|  |  | ||||||
|     strcpy(buf, prefix); |  | ||||||
|     strcpy(buf + prefixlen, suffix); |  | ||||||
|  |  | ||||||
|     return buf; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static | static | ||||||
| inline | inline | ||||||
| @@ -96,17 +80,17 @@ split_argv(const char *argv0, | |||||||
|            char **exe_ptr) |            char **exe_ptr) | ||||||
| { | { | ||||||
|     const char *sep = _tcsrchrs(argv0, '/', '\\'); |     const char *sep = _tcsrchrs(argv0, '/', '\\'); | ||||||
|  |     const char *basename_ptr_const = argv0; | ||||||
|     char *dir = strdup(_T("")); |     char *dir = strdup(_T("")); | ||||||
|     const char *basename = argv0; |  | ||||||
|  |  | ||||||
|     if(sep) |     if(sep) | ||||||
|     { |     { | ||||||
|         dir = strdup(argv0); |         dir = strdup(argv0); | ||||||
|         dir[sep + 1 - argv0] = '\0'; |         dir[sep + 1 - argv0] = '\0'; | ||||||
|         basename = sep + 1; |         basename_ptr_const = sep + 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     basename = strdup(basename); |     char *basename = strdup(basename_ptr_const); | ||||||
|     char *period = strchr(basename, '.'); |     char *period = strchr(basename, '.'); | ||||||
|  |  | ||||||
|     if(period) |     if(period) | ||||||
| @@ -116,7 +100,7 @@ split_argv(const char *argv0, | |||||||
|  |  | ||||||
|     char *target = strdup(basename); |     char *target = strdup(basename); | ||||||
|     char *dash = strrchr(target, '-'); |     char *dash = strrchr(target, '-'); | ||||||
|     const char *exe = basename; |     char *exe = basename; | ||||||
|  |  | ||||||
|     if(dash) |     if(dash) | ||||||
|     { |     { | ||||||
| @@ -148,15 +132,3 @@ split_argv(const char *argv0, | |||||||
|         *exe_ptr = exe; |         *exe_ptr = exe; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static |  | ||||||
| inline |  | ||||||
| int |  | ||||||
| run_final(const char *executable, |  | ||||||
|           const char *const *argv) |  | ||||||
| { |  | ||||||
|     execvp(executable, (char **) argv); |  | ||||||
|     perror(executable); |  | ||||||
|  |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -14,9 +14,8 @@ | |||||||
|  |  | ||||||
| #include "xtchain.h" | #include "xtchain.h" | ||||||
|  |  | ||||||
| #define XTCSPECC_VERSION "1.2" |  | ||||||
|  |  | ||||||
| #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) | #define XTCSPECC_VERSION "1.2" | ||||||
|  |  | ||||||
| typedef struct _STRING | typedef struct _STRING | ||||||
| { | { | ||||||
| @@ -77,12 +76,12 @@ enum | |||||||
|  |  | ||||||
| enum | enum | ||||||
| { | { | ||||||
|     CC_STDCALL, |     CCONV_STDCALL, | ||||||
|     CC_CDECL, |     CCONV_CDECL, | ||||||
|     CC_FASTCALL, |     CCONV_FASTCALL, | ||||||
|     CC_THISCALL, |     CCONV_THISCALL, | ||||||
|     CC_EXTERN, |     CCONV_EXTERN, | ||||||
|     CC_STUB, |     CCONV_STUB, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum | enum | ||||||
| @@ -257,11 +256,11 @@ OutputLine_stub(FILE *file, | |||||||
|     int bRelay = 0; |     int bRelay = 0; | ||||||
|     int bInPrototype = 0; |     int bInPrototype = 0; | ||||||
|  |  | ||||||
|     if(pexp->nCallingConvention != CC_STUB && |     if(pexp->nCallingConvention != CCONV_STUB && | ||||||
|        (pexp->uFlags & FL_STUB) == 0) |        (pexp->uFlags & FL_STUB) == 0) | ||||||
|     { |     { | ||||||
|         /* Only relay trace stdcall C functions */ |         /* Only relay trace stdcall C functions */ | ||||||
|         if(!gbTracing || (pexp->nCallingConvention != CC_STDCALL) || |         if(!gbTracing || (pexp->nCallingConvention != CCONV_STDCALL) || | ||||||
|            (pexp->uFlags & FL_NORELAY) || |            (pexp->uFlags & FL_NORELAY) || | ||||||
|            (pexp->strName.buf[0] == '?')) |            (pexp->strName.buf[0] == '?')) | ||||||
|         { |         { | ||||||
| @@ -294,7 +293,7 @@ OutputLine_stub(FILE *file, | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if((giArch == ARCH_X86) && |         if((giArch == ARCH_X86) && | ||||||
|             pexp->nCallingConvention == CC_STDCALL) |             pexp->nCallingConvention == CCONV_STDCALL) | ||||||
|         { |         { | ||||||
|             fprintf(file, "__stdcall "); |             fprintf(file, "__stdcall "); | ||||||
|         } |         } | ||||||
| @@ -398,7 +397,7 @@ OutputLine_stub(FILE *file, | |||||||
|     } |     } | ||||||
|     fprintf(file, ");\n"); |     fprintf(file, ");\n"); | ||||||
|  |  | ||||||
|     if(pexp->nCallingConvention == CC_STUB) |     if(pexp->nCallingConvention == CCONV_STUB) | ||||||
|     { |     { | ||||||
|         fprintf(file, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName); |         fprintf(file, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName); | ||||||
|     } |     } | ||||||
| @@ -510,8 +509,8 @@ PrintName(FILE *fileDest, | |||||||
|         fprintf(fileDest, "%.*s", nNameLength, pcName); |         fprintf(fileDest, "%.*s", nNameLength, pcName); | ||||||
|     } |     } | ||||||
|     else if(fDeco && |     else if(fDeco && | ||||||
|             ((pexp->nCallingConvention == CC_STDCALL) || |             ((pexp->nCallingConvention == CCONV_STDCALL) || | ||||||
|              (pexp->nCallingConvention == CC_FASTCALL))) |              (pexp->nCallingConvention == CCONV_FASTCALL))) | ||||||
|     { |     { | ||||||
|         /* Scan for a dll forwarding dot */ |         /* Scan for a dll forwarding dot */ | ||||||
|         pcDot = ScanToken(pcName, '.'); |         pcDot = ScanToken(pcName, '.'); | ||||||
| @@ -536,9 +535,9 @@ PrintName(FILE *fileDest, | |||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             /* Print the prefix, but skip it for stdcall */ |             /* Print the prefix, but skip it for stdcall */ | ||||||
|             if(pexp->nCallingConvention != CC_STDCALL) |             if(pexp->nCallingConvention != CCONV_STDCALL) | ||||||
|             { |             { | ||||||
|                 fprintf(fileDest, "%c", pexp->nCallingConvention == CC_FASTCALL ? '@' : '_'); |                 fprintf(fileDest, "%c", pexp->nCallingConvention == CCONV_FASTCALL ? '@' : '_'); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             /* Print the name with trailing decoration */ |             /* Print the name with trailing decoration */ | ||||||
| @@ -581,8 +580,8 @@ OutputLine_def(FILE *fileDest, | |||||||
|             /* If the original name was decorated, use decoration in the forwarder as well */ |             /* If the original name was decorated, use decoration in the forwarder as well */ | ||||||
|             if((giArch == ARCH_X86) && ScanToken(pexp->strName.buf, '@') && |             if((giArch == ARCH_X86) && ScanToken(pexp->strName.buf, '@') && | ||||||
|                 !ScanToken(pexp->strTarget.buf, '@') && |                 !ScanToken(pexp->strTarget.buf, '@') && | ||||||
|                 ((pexp->nCallingConvention == CC_STDCALL) || |                 ((pexp->nCallingConvention == CCONV_STDCALL) || | ||||||
|                 (pexp->nCallingConvention == CC_FASTCALL)) ) |                 (pexp->nCallingConvention == CCONV_FASTCALL)) ) | ||||||
|             { |             { | ||||||
|                 PrintName(fileDest, pexp, &pexp->strTarget, 1); |                 PrintName(fileDest, pexp, &pexp->strTarget, 1); | ||||||
|             } |             } | ||||||
| @@ -593,13 +592,13 @@ OutputLine_def(FILE *fileDest, | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else if(((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) && |     else if(((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CCONV_STUB)) && | ||||||
|              (pexp->strName.buf[0] == '?')) |              (pexp->strName.buf[0] == '?')) | ||||||
|     { |     { | ||||||
|         /* C++ stubs are forwarded to C stubs */ |         /* C++ stubs are forwarded to C stubs */ | ||||||
|         fprintf(fileDest, "=stub_function%d", pexp->nNumber); |         fprintf(fileDest, "=stub_function%d", pexp->nNumber); | ||||||
|     } |     } | ||||||
|     else if(gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) && (pexp->nCallingConvention == CC_STDCALL) && |     else if(gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) && (pexp->nCallingConvention == CCONV_STDCALL) && | ||||||
|             (pexp->strName.buf[0] != '?')) |             (pexp->strName.buf[0] != '?')) | ||||||
|     { |     { | ||||||
|         /* Redirect it to the relay-tracing trampoline */ |         /* Redirect it to the relay-tracing trampoline */ | ||||||
| @@ -616,7 +615,7 @@ OutputLine_def(FILE *fileDest, | |||||||
|     { |     { | ||||||
|         fprintf(fileDest, " PRIVATE"); |         fprintf(fileDest, " PRIVATE"); | ||||||
|     } |     } | ||||||
|     else if(pexp->nCallingConvention == CC_EXTERN) |     else if(pexp->nCallingConvention == CCONV_EXTERN) | ||||||
|     { |     { | ||||||
|         fprintf(fileDest, " DATA"); |         fprintf(fileDest, " DATA"); | ||||||
|     } |     } | ||||||
| @@ -798,28 +797,28 @@ ParseFile(char* pcStart, | |||||||
|         /* Now we should get the type */ |         /* Now we should get the type */ | ||||||
|         if(CompareToken(pc, "stdcall")) |         if(CompareToken(pc, "stdcall")) | ||||||
|         { |         { | ||||||
|             exp.nCallingConvention = CC_STDCALL; |             exp.nCallingConvention = CCONV_STDCALL; | ||||||
|         } |         } | ||||||
|         else if(CompareToken(pc, "cdecl") || |         else if(CompareToken(pc, "cdecl") || | ||||||
|                  CompareToken(pc, "varargs")) |                  CompareToken(pc, "varargs")) | ||||||
|         { |         { | ||||||
|             exp.nCallingConvention = CC_CDECL; |             exp.nCallingConvention = CCONV_CDECL; | ||||||
|         } |         } | ||||||
|         else if(CompareToken(pc, "fastcall")) |         else if(CompareToken(pc, "fastcall")) | ||||||
|         { |         { | ||||||
|             exp.nCallingConvention = CC_FASTCALL; |             exp.nCallingConvention = CCONV_FASTCALL; | ||||||
|         } |         } | ||||||
|         else if(CompareToken(pc, "thiscall")) |         else if(CompareToken(pc, "thiscall")) | ||||||
|         { |         { | ||||||
|             exp.nCallingConvention = CC_THISCALL; |             exp.nCallingConvention = CCONV_THISCALL; | ||||||
|         } |         } | ||||||
|         else if(CompareToken(pc, "extern")) |         else if(CompareToken(pc, "extern")) | ||||||
|         { |         { | ||||||
|             exp.nCallingConvention = CC_EXTERN; |             exp.nCallingConvention = CCONV_EXTERN; | ||||||
|         } |         } | ||||||
|         else if(CompareToken(pc, "stub")) |         else if(CompareToken(pc, "stub")) | ||||||
|         { |         { | ||||||
|             exp.nCallingConvention = CC_STUB; |             exp.nCallingConvention = CCONV_STUB; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -986,8 +985,8 @@ ParseFile(char* pcStart, | |||||||
|  |  | ||||||
|         /* Handle parameters */ |         /* Handle parameters */ | ||||||
|         exp.nStackBytes = 0; |         exp.nStackBytes = 0; | ||||||
|         if(exp.nCallingConvention != CC_EXTERN && |         if(exp.nCallingConvention != CCONV_EXTERN && | ||||||
|            exp.nCallingConvention != CC_STUB) |            exp.nCallingConvention != CCONV_STUB) | ||||||
|         { |         { | ||||||
|             /* Go to next token */ |             /* Go to next token */ | ||||||
|             if(!(pc = NextToken(pc))) |             if(!(pc = NextToken(pc))) | ||||||
| @@ -1069,7 +1068,7 @@ ParseFile(char* pcStart, | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /* Handle special stub cases */ |         /* Handle special stub cases */ | ||||||
|         if(exp.nCallingConvention == CC_STUB) |         if(exp.nCallingConvention == CCONV_STUB) | ||||||
|         { |         { | ||||||
|             /* Check for c++ mangled name */ |             /* Check for c++ mangled name */ | ||||||
|             if(pc[0] == '?') |             if(pc[0] == '?') | ||||||
| @@ -1093,7 +1092,7 @@ ParseFile(char* pcStart, | |||||||
|                     } |                     } | ||||||
|                     exp.nStackBytes = atoi(p + 1); |                     exp.nStackBytes = atoi(p + 1); | ||||||
|                     exp.nArgCount =  exp.nStackBytes / 4; |                     exp.nArgCount =  exp.nStackBytes / 4; | ||||||
|                     exp.nCallingConvention = CC_STDCALL; |                     exp.nCallingConvention = CCONV_STDCALL; | ||||||
|                     exp.uFlags |= FL_STUB; |                     exp.uFlags |= FL_STUB; | ||||||
|                     for(i = 0; i < exp.nArgCount; i++) |                     for(i = 0; i < exp.nArgCount; i++) | ||||||
|                     { |                     { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user