diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9170e8a..ca6ae18 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,18 +3,27 @@ run-name: ${{ github.actor }} runs Gitea Actions on: [push] jobs: - XTChain: + XTchain: + strategy: + matrix: + target: [linux, windows] + build: [full, minimal] runs-on: oscw container: image: codingworkshop/oscw-runner:latest steps: - name: Clone repository uses: actions/checkout@v3 - - name: Build XTChain - run: CORES=10 ./build-linux.sh + - name: Build XTchain + 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 if: startsWith(github.ref, 'refs/tags/') env: OSCW_GITHUB_USERNAME: ${{ secrets.OSCW_GITHUB_USERNAME }} 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 }}.*) diff --git a/README.md b/README.md index 5aaf6ae..3e41a1d 100644 --- a/README.md +++ b/README.md @@ -22,31 +22,28 @@ --- ## XT Toolchain -This is a LLVM/Clang/LLD based mingw-w64 toolchain. It currently supports C and C++, and provides -a variety of tools including IDL, message and resource compilers. The XT Toolchain is also the -official build environment for compiling XT software, including the XT OS. Currently, it is -targeted at Linux host only, however it should be possible to build it in MSYS2 as well. +The XT Toolchain is a build environment based on LLVM/Clang/LLD. It currently supports C and C++, and includes +a variety of auxiliary tools such as IDL, message, and resource compilers. The XT Toolchain is the official +build system for compiling XT software, including the XT OS. It is currently available for Linux and Windows +host systems. -Benefits of a LLVM based MinGW toolchain are: - * Single toolchain targeting all architectures (i686, x86_64, armv7 and aarch64), - * Support for generating debug info in PDB format, - * Support for targeting ARM/AARCH64 architectures and ability to produce Windows ARM binaries. +Key Benefits of using an LLVM-based Toolchain: + * Unified toolchain for multiple target architectures: i686, x86_64, armv7, and aarch64 + * Support for generating debug information in PDB format + * Ability to target ARM/AArch64 architectures and produce ARM binaries -This software includes: +This toolchain includes the following software: * CMake - * GNU Assembler * LLVM - * Make - * Mingw-w64 * Ninja * 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 -The XTchain project includes the scripts for building and assembling a toolchain as well as wrappers -for LLVM tools and environmental shell. These are licensed under the GPLv3 license. It covers only -mentioned components that are provided by XTchain directly. For more information on that, refer to -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 -README.md file. +The XTchain project includes scripts for building and assembling the toolchain, as well as the environment +shell. These components are licensed under the GNU GPLv3 license. This license applies only to the parts +provided directly by XTchain. For detailed information, please refer to the COPYING.md file. + +The final pre-built toolchain is subject to the licenses of the individual third-party projects it includes. +A complete list of the external software used in this toolchain can be found in the README.md file. diff --git a/build-linux.sh b/build-linux.sh deleted file mode 100755 index b5ed3b2..0000000 --- a/build-linux.sh +++ /dev/null @@ -1,566 +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 - - -# 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" - -# CMake Settings -CMAKEDIR="${SRCDIR}/cmake" -CMAKETAG="v3.31.3" -CMAKEVCS="https://gitlab.kitware.com/cmake/cmake.git" - -# LLVM Settings -LLVMDIR="${SRCDIR}/llvm" -LLVMTAG="llvmorg-19.1.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.12.1" -NINJAVCS="https://github.com/ninja-build/ninja.git" - -# Wine Settings -WINEDIR="${SRCDIR}/wine" -WINETAG="wine-9.8" -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() -{ - 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 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 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} . diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..d46b9ec --- /dev/null +++ b/build.sh @@ -0,0 +1,499 @@ +#!/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 +# Aiken Harris + +# 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.0.3" +CMAKEVCS="https://gitlab.kitware.com/cmake/cmake.git" + +# LLVM Settings +LLVMDIR="${SRCDIR}/llvm" +LLVMTAG="llvmorg-20.1.7" +LLVMVCS="https://github.com/llvm/llvm-project.git" + +# Ninja Settings +NINJADIR="${SRCDIR}/ninja" +NINJATAG="v1.13.0" +NINJAVCS="https://github.com/ninja-build/ninja.git" + +# Wine Settings +WINEDIR="${SRCDIR}/wine" +WINETAG="wine-10.11" +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 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" + EXTENSION=".ps1" + ;; + *) + CCOMPILER="clang" + EXTENSION="" + esac + + # Build XTchain tools + echo ">>> Building XTchain tools ..." + mkdir -p ${BINDIR}/bin + mkdir -p ${BINDIR}/lib/xtchain + for EXEC in bin2c exetool xtcspecc; do + if [ ! -e ${BINDIR}/bin/${EXEC} ]; then + ${CCOMPILER} ${WRKDIR}/tools/${EXEC}.c -o ${BINDIR}/bin/${EXEC} + fi + done + cp ${WRKDIR}/scripts/xtclib${EXTENSION} ${BINDIR}/lib/xtchain/ + cp ${WRKDIR}/scripts/xtchain${EXTENSION} ${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}-min" + 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 + +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 diff --git a/patches/cmake/v3.29.3/001-add-xtc-version-suffix.patch b/patches/cmake/v3.29.3/001-add-xtc-version-suffix.patch deleted file mode 100644 index 7319cbf..0000000 --- a/patches/cmake/v3.29.3/001-add-xtc-version-suffix.patch +++ /dev/null @@ -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() diff --git a/patches/cmake/v3.31.3/001-add-xtc-version-suffix.patch b/patches/cmake/v3.31.3/001-add-xtc-version-suffix.patch deleted file mode 100644 index 7319cbf..0000000 --- a/patches/cmake/v3.31.3/001-add-xtc-version-suffix.patch +++ /dev/null @@ -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() diff --git a/patches/mingw-w64/v8.0.0/001-widl-sltg-support.patch b/patches/mingw-w64/v8.0.0/001-widl-sltg-support.patch deleted file mode 100644 index c618bf5..0000000 --- a/patches/mingw-w64/v8.0.0/001-widl-sltg-support.patch +++ /dev/null @@ -1,2013 +0,0 @@ -diff -apurN a/mingw-w64-tools/widl/Makefile.am b/mingw-w64-tools/widl/Makefile.am ---- a/mingw-w64-tools/widl/Makefile.am 2020-10-13 16:23:12.944066396 +0200 -+++ b/mingw-w64-tools/widl/Makefile.am 2020-10-13 16:19:00.523221067 +0200 -@@ -29,6 +29,7 @@ widl_SOURCES = src/widl.h \ - src/utils.c \ - src/widl.c \ - src/write_msft.c \ -+ src/write_sltg.c \ - src/wpp/wpp_private.h \ - src/wpp/ppy.tab.h \ - src/wpp/ppl.yy.c \ -diff -apurN a/mingw-w64-tools/widl/Makefile.in b/mingw-w64-tools/widl/Makefile.in ---- a/mingw-w64-tools/widl/Makefile.in 2020-10-13 16:23:12.944066396 +0200 -+++ b/mingw-w64-tools/widl/Makefile.in 2020-10-13 16:21:19.069027341 +0200 -@@ -117,7 +117,8 @@ am_widl_OBJECTS = src/widl-client.$(OBJE - src/widl-utils.$(OBJEXT) src/widl-widl.$(OBJEXT) \ - src/widl-write_msft.$(OBJEXT) src/wpp/widl-ppl.yy.$(OBJEXT) \ - src/wpp/widl-ppy.tab.$(OBJEXT) src/wpp/widl-preproc.$(OBJEXT) \ -- src/wpp/widl-wpp.$(OBJEXT) src/widl-pathtools.$(OBJEXT) -+ src/wpp/widl-wpp.$(OBJEXT) src/widl-pathtools.$(OBJEXT) \ -+ src/widl-write_sltg.$(OBJEXT) - widl_OBJECTS = $(am_widl_OBJECTS) - widl_LDADD = $(LDADD) - widl_LINK = $(CCLD) $(widl_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -@@ -356,6 +357,7 @@ widl_SOURCES = src/widl.h \ - src/utils.c \ - src/widl.c \ - src/write_msft.c \ -+ src/write_sltg.c \ - src/wpp/wpp_private.h \ - src/wpp/ppy.tab.h \ - src/wpp/ppl.yy.c \ -@@ -527,6 +529,8 @@ src/widl-widl.$(OBJEXT): src/$(am__dirst - src/$(DEPDIR)/$(am__dirstamp) - src/widl-write_msft.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -+src/widl-write_sltg.$(OBJEXT): src/$(am__dirstamp) \ -+ src/$(DEPDIR)/$(am__dirstamp) - src/wpp/$(am__dirstamp): - @$(MKDIR_P) src/wpp - @: > src/wpp/$(am__dirstamp) -@@ -840,6 +845,20 @@ src/widl-write_msft.obj: src/write_msft. - @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -c -o src/widl-write_msft.obj `if test -f 'src/write_msft.c'; then $(CYGPATH_W) 'src/write_msft.c'; else $(CYGPATH_W) '$(srcdir)/src/write_msft.c'; fi` - -+src/widl-write_sltg.o: src/write_sltg.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -MT src/widl-write_sltg.o -MD -MP -MF src/$(DEPDIR)/widl-write_sltg.Tpo -c -o src/widl-write_sltg.o `test -f 'src/write_sltg.c' || echo '$(srcdir)/'`src/write_sltg.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/widl-write_sltg.Tpo src/$(DEPDIR)/widl-write_sltg.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/write_sltg.c' object='src/widl-write_sltg.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -c -o src/widl-write_sltg.o `test -f 'src/write_sltg.c' || echo '$(srcdir)/'`src/write_sltg.c -+ -+src/widl-write_sltg.obj: src/write_sltg.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -MT src/widl-write_sltg.obj -MD -MP -MF src/$(DEPDIR)/widl-write_sltg.Tpo -c -o src/widl-write_sltg.obj `if test -f 'src/write_sltg.c'; then $(CYGPATH_W) 'src/write_sltg.c'; else $(CYGPATH_W) '$(srcdir)/src/write_sltg.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/widl-write_sltg.Tpo src/$(DEPDIR)/widl-write_sltg.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/write_sltg.c' object='src/widl-write_sltg.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -c -o src/widl-write_sltg.obj `if test -f 'src/write_sltg.c'; then $(CYGPATH_W) 'src/write_sltg.c'; else $(CYGPATH_W) '$(srcdir)/src/write_sltg.c'; fi` -+ - src/wpp/widl-ppl.yy.o: src/wpp/ppl.yy.c - @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -MT src/wpp/widl-ppl.yy.o -MD -MP -MF src/wpp/$(DEPDIR)/widl-ppl.yy.Tpo -c -o src/wpp/widl-ppl.yy.o `test -f 'src/wpp/ppl.yy.c' || echo '$(srcdir)/'`src/wpp/ppl.yy.c - @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/wpp/$(DEPDIR)/widl-ppl.yy.Tpo src/wpp/$(DEPDIR)/widl-ppl.yy.Po -diff -apurN a/mingw-w64-tools/widl/src/register.c b/mingw-w64-tools/widl/src/register.c ---- a/mingw-w64-tools/widl/src/register.c 2020-10-13 16:23:12.950066345 +0200 -+++ b/mingw-w64-tools/widl/src/register.c 2020-10-13 16:19:00.523221067 +0200 -@@ -281,7 +281,12 @@ void write_typelib_regscript( const stat - if (count && !strendswith( typelib_name, ".res" )) - error( "Cannot store multiple typelibs into %s\n", typelib_name ); - else -- create_msft_typelib( stmt->u.lib ); -+ { -+ if (do_old_typelib) -+ create_sltg_typelib( stmt->u.lib ); -+ else -+ create_msft_typelib( stmt->u.lib ); -+ } - count++; - } - if (count && strendswith( typelib_name, ".res" )) flush_output_resources( typelib_name ); -diff -apurN a/mingw-w64-tools/widl/src/typelib.h b/mingw-w64-tools/widl/src/typelib.h ---- a/mingw-w64-tools/widl/src/typelib.h 2020-10-13 16:23:12.950066345 +0200 -+++ b/mingw-w64-tools/widl/src/typelib.h 2020-10-13 16:19:00.523221067 +0200 -@@ -83,4 +83,5 @@ enum VARENUM { - extern unsigned short get_type_vt(type_t *t); - - extern int create_msft_typelib(typelib_t *typelib); -+extern int create_sltg_typelib(typelib_t *typelib); - #endif -diff -apurN a/mingw-w64-tools/widl/src/widl.c b/mingw-w64-tools/widl/src/widl.c ---- a/mingw-w64-tools/widl/src/widl.c 2020-10-13 16:23:12.951066337 +0200 -+++ b/mingw-w64-tools/widl/src/widl.c 2020-10-13 16:22:05.493635687 +0200 -@@ -64,6 +64,7 @@ static const char usage[] = - " --nostdinc Do not search the standard include path\n" - " --ns_prefix Prefix namespaces with ABI namespace\n" - " --oldnames Use old naming conventions\n" -+" --oldtlb Use old typelib (SLTG) format\n" - " -o, --output=NAME Set the output file name\n" - " -Otype Type of stubs to generate (-Os, -Oi, -Oif)\n" - " -p Generate proxy\n" -@@ -116,6 +117,7 @@ int do_everything = 1; - static int preprocess_only = 0; - int do_header = 0; - int do_typelib = 0; -+int do_old_typelib = 0; - int do_proxies = 0; - int do_client = 0; - int do_server = 0; -@@ -168,6 +170,7 @@ enum { - DLLDATA_OPTION, - DLLDATA_ONLY_OPTION, - LOCAL_STUBS_OPTION, -+ OLD_TYPELIB_OPTION, - NOSTDINC_OPTION, - PREFIX_ALL_OPTION, - PREFIX_CLIENT_OPTION, -@@ -195,6 +198,7 @@ static const struct option long_options[ - { "nostdinc", 0, NULL, NOSTDINC_OPTION }, - { "ns_prefix", 0, NULL, RT_NS_PREFIX }, - { "oldnames", 0, NULL, OLDNAMES_OPTION }, -+ { "oldtlb", 0, NULL, OLD_TYPELIB_OPTION }, - { "output", 0, NULL, 'o' }, - { "prefix-all", 1, NULL, PREFIX_ALL_OPTION }, - { "prefix-client", 1, NULL, PREFIX_CLIENT_OPTION }, -@@ -333,6 +337,7 @@ static void set_everything(int x) - { - do_header = x; - do_typelib = x; -+ do_old_typelib = x; - do_proxies = x; - do_client = x; - do_server = x; -@@ -749,6 +754,9 @@ int main(int argc,char *argv[]) - do_everything = 0; - do_typelib = 1; - break; -+ case OLD_TYPELIB_OPTION: -+ do_old_typelib = 1; -+ break; - case 'T': - typelib_name = xstrdup(optarg); - break; -diff -apurN a/mingw-w64-tools/widl/src/widl.h b/mingw-w64-tools/widl/src/widl.h ---- a/mingw-w64-tools/widl/src/widl.h 2020-10-13 16:23:12.951066337 +0200 -+++ b/mingw-w64-tools/widl/src/widl.h 2020-10-13 16:19:00.524221058 +0200 -@@ -38,6 +38,7 @@ extern int pedantic; - extern int do_everything; - extern int do_header; - extern int do_typelib; -+extern int do_old_typelib; - extern int do_proxies; - extern int do_client; - extern int do_server; -diff -apurN a/mingw-w64-tools/widl/src/write_sltg.c b/mingw-w64-tools/widl/src/write_sltg.c ---- a/mingw-w64-tools/widl/src/write_sltg.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/mingw-w64-tools/widl/src/write_sltg.c 2020-10-13 16:19:00.524221058 +0200 -@@ -0,0 +1,1857 @@ -+/* -+ * Typelib (SLTG) generation -+ * -+ * Copyright 2015,2016 Dmitry Timoshkov -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "config.h" -+#include "wine/port.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define NONAMELESSUNION -+ -+#include "windef.h" -+#include "winbase.h" -+ -+#include "widl.h" -+#include "typelib.h" -+#include "typelib_struct.h" -+#include "utils.h" -+#include "header.h" -+#include "typetree.h" -+ -+static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } }; -+ -+struct sltg_data -+{ -+ int size, allocated; -+ char *data; -+}; -+ -+struct sltg_library -+{ -+ short name; -+ char *helpstring; -+ char *helpfile; -+ int helpcontext; -+ int syskind; -+ LCID lcid; -+ int libflags; -+ int version; -+ GUID uuid; -+}; -+ -+struct sltg_block -+{ -+ int length; -+ int index_string; -+ void *data; -+ struct sltg_block *next; -+}; -+ -+struct sltg_typelib -+{ -+ typelib_t *typelib; -+ struct sltg_data index; -+ struct sltg_data name_table; -+ struct sltg_library library; -+ struct sltg_block *blocks; -+ int n_file_blocks; -+ int first_block; -+ int typeinfo_count; -+ int typeinfo_size; -+ struct sltg_block *typeinfo; -+}; -+ -+struct sltg_hrefmap -+{ -+ int href_count; -+ int *href; -+}; -+ -+#include "pshpack1.h" -+struct sltg_typeinfo_header -+{ -+ short magic; -+ int href_offset; -+ int res06; -+ int member_offset; -+ int res0e; -+ int version; -+ int res16; -+ struct -+ { -+ unsigned unknown1 : 3; -+ unsigned flags : 13; -+ unsigned unknown2 : 8; -+ unsigned typekind : 8; -+ } misc; -+ int res1e; -+}; -+ -+struct sltg_member_header -+{ -+ short res00; -+ short res02; -+ char res04; -+ int extra; -+}; -+ -+struct sltg_variable -+{ -+ char magic; /* 0x0a */ -+ char flags; -+ short next; -+ short name; -+ short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */ -+ short type; /* if flags & 0x02 this is the type, else offset to type */ -+ int memid; -+ short helpcontext; -+ short helpstring; -+ short varflags; /* only present if magic & 0x02 */ -+}; -+ -+struct sltg_tail -+{ -+ short cFuncs; -+ short cVars; -+ short cImplTypes; -+ short res06; /* always 0000 */ -+ short funcs_off; /* offset to functions (starting from the member header) */ -+ short vars_off; /* offset to vars (starting from the member header) */ -+ short impls_off; /* offset to implemented types (starting from the member header) */ -+ short funcs_bytes; /* bytes used by function data */ -+ short vars_bytes; /* bytes used by var data */ -+ short impls_bytes; /* bytes used by implemented type data */ -+ short tdescalias_vt; /* for TKIND_ALIAS */ -+ short res16; /* always ffff */ -+ short res18; /* always 0000 */ -+ short res1a; /* always 0000 */ -+ short simple_alias; /* tdescalias_vt is a vt rather than an offset? */ -+ short res1e; /* always 0000 */ -+ short cbSizeInstance; -+ short cbAlignment; -+ short res24; -+ short res26; -+ short cbSizeVft; -+ short res2a; /* always ffff */ -+ short res2c; /* always ffff */ -+ short res2e; /* always ffff */ -+ short res30; /* always ffff */ -+ short res32; /* unknown */ -+ short type_bytes; /* bytes used by type descriptions */ -+}; -+ -+struct sltg_hrefinfo -+{ -+ char magic; /* 0xdf */ -+ char res01; /* 0x00 */ -+ int res02; /* 0xffffffff */ -+ int res06; /* 0xffffffff */ -+ int res0a; /* 0xffffffff */ -+ int res0e; /* 0xffffffff */ -+ int res12; /* 0xffffffff */ -+ int res16; /* 0xffffffff */ -+ int res1a; /* 0xffffffff */ -+ int res1e; /* 0xffffffff */ -+ int res22; /* 0xffffffff */ -+ int res26; /* 0xffffffff */ -+ int res2a; /* 0xffffffff */ -+ int res2e; /* 0xffffffff */ -+ int res32; /* 0xffffffff */ -+ int res36; /* 0xffffffff */ -+ int res3a; /* 0xffffffff */ -+ int res3e; /* 0xffffffff */ -+ short res42;/* 0xffff */ -+ int number; /* this is 8 times the number of refs */ -+ /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */ -+ -+ short res50;/* 0xffff */ -+ char res52; /* 0x01 */ -+ int res53; /* 0x00000000 */ -+ /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii -+ * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the -+ * ref refers to the nth type listed in this library (0 based). Else -+ * the xxxx (which maybe fewer than 4 digits) is the offset into the name -+ * table to a string "*\G{}#1.0#0#C:\WINNT\System32\stdole32.tlb#" -+ * The guid is the typelib guid; the ref again refers to the nth type of -+ * the imported typelib. -+ */ -+ -+ char resxx; /* 0xdf */ -+}; -+ -+struct sltg_function -+{ -+ char magic; /* 0x4c, 0xcb or 0x8b with optional SLTG_FUNCTION_FLAGS_PRESENT flag */ -+ char flags; /* high nibble is INVOKE_KIND, low nibble = 2 */ -+ short next; /* byte offset from beginning of group to next fn */ -+ short name; /* Offset within name table to name */ -+ int dispid; /* dispid */ -+ short helpcontext; /* helpcontext (again 1 is special) */ -+ short helpstring; /* helpstring offset to offset */ -+ short arg_off; /* offset to args from start of block */ -+ char nacc; /* lowest 3bits are CALLCONV, rest are no of args */ -+ char retnextopt; /* if 0x80 bit set ret type follows else next WORD -+ is offset to ret type. No of optional args is -+ middle 6 bits */ -+ short rettype; /* return type VT_?? or offset to ret type */ -+ short vtblpos; /* position in vtbl? */ -+ short funcflags; /* present if magic & 0x20 */ -+/* Param list starts, repeat next two as required */ -+#if 0 -+ WORD name; /* offset to 2nd letter of name */ -+ WORD+ type; /* VT_ of param */ -+#endif -+}; -+ -+struct sltg_impl_info -+{ -+ short res00; -+ short next; -+ short res04; -+ char impltypeflags; -+ char res07; -+ short res08; -+ short ref; -+ short res0c; -+ short res0e; -+ short res10; -+ short res12; -+ short pos; -+}; -+ -+#include "poppack.h" -+ -+static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type); -+static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type); -+static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type); -+static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type); -+static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type); -+ -+static void init_sltg_data(struct sltg_data *data) -+{ -+ data->size = 0; -+ data->allocated = 0x10; -+ data->data = xmalloc(0x10); -+} -+ -+static int add_index(struct sltg_data *index, const char *name) -+{ -+ int name_offset = index->size; -+ int new_size = index->size + strlen(name) + 1; -+ -+ chat("add_index: name_offset %d, \"%s\"\n", name_offset, name); -+ -+ if (new_size > index->allocated) -+ { -+ index->allocated = max(index->allocated * 2, new_size); -+ index->data = xrealloc(index->data, index->allocated); -+ } -+ -+ strcpy(index->data + index->size, name); -+ index->size = new_size; -+ -+ return name_offset; -+} -+ -+static void init_index(struct sltg_data *index) -+{ -+ static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 }; -+ -+ init_sltg_data(index); -+ -+ add_index(index, compobj); -+} -+ -+static int add_name(struct sltg_typelib *sltg, const char *name) -+{ -+ int name_offset = sltg->name_table.size; -+ int new_size = sltg->name_table.size + strlen(name) + 1 + 8; -+ int aligned_size; -+ -+ chat("add_name: %s\n", name); -+ -+ aligned_size = (new_size + 0x1f) & ~0x1f; -+ if (aligned_size - new_size < 4) -+ new_size = aligned_size; -+ else -+ new_size = (new_size + 1) & ~1; -+ -+ if (new_size > sltg->name_table.allocated) -+ { -+ sltg->name_table.allocated = max(sltg->name_table.allocated * 2, new_size); -+ sltg->name_table.data = xrealloc(sltg->name_table.data, sltg->name_table.allocated); -+ } -+ -+ memset(sltg->name_table.data + sltg->name_table.size, 0xff, 8); -+ strcpy(sltg->name_table.data + sltg->name_table.size + 8, name); -+ sltg->name_table.size = new_size; -+ sltg->name_table.data[sltg->name_table.size - 1] = 0; /* clear alignment */ -+ -+ return name_offset; -+} -+ -+static void init_name_table(struct sltg_typelib *sltg) -+{ -+ init_sltg_data(&sltg->name_table); -+} -+ -+static void init_library(struct sltg_typelib *sltg) -+{ -+ const attr_t *attr; -+ -+ sltg->library.name = add_name(sltg, sltg->typelib->name); -+ sltg->library.helpstring = NULL; -+ sltg->library.helpcontext = 0; -+ sltg->library.syskind = (pointer_size == 8) ? SYS_WIN64 : SYS_WIN32; -+ sltg->library.lcid = 0x0409; -+ sltg->library.libflags = 0; -+ sltg->library.version = 0; -+ sltg->library.helpfile = NULL; -+ memset(&sltg->library.uuid, 0, sizeof(sltg->library.uuid)); -+ -+ if (!sltg->typelib->attrs) return; -+ -+ LIST_FOR_EACH_ENTRY(attr, sltg->typelib->attrs, const attr_t, entry) -+ { -+ const expr_t *expr; -+ -+ switch (attr->type) -+ { -+ case ATTR_VERSION: -+ sltg->library.version = attr->u.ival; -+ break; -+ case ATTR_HELPSTRING: -+ sltg->library.helpstring = attr->u.pval; -+ break; -+ case ATTR_HELPFILE: -+ sltg->library.helpfile = attr->u.pval; -+ break; -+ case ATTR_UUID: -+ sltg->library.uuid = *(GUID *)attr->u.pval; -+ break; -+ case ATTR_HELPCONTEXT: -+ expr = attr->u.pval; -+ sltg->library.helpcontext = expr->cval; -+ break; -+ case ATTR_LIBLCID: -+ expr = attr->u.pval; -+ sltg->library.lcid = expr->cval; -+ break; -+ case ATTR_CONTROL: -+ sltg->library.libflags |= 0x02; /* LIBFLAG_FCONTROL */ -+ break; -+ case ATTR_HIDDEN: -+ sltg->library.libflags |= 0x04; /* LIBFLAG_FHIDDEN */ -+ break; -+ case ATTR_RESTRICTED: -+ sltg->library.libflags |= 0x01; /* LIBFLAG_FRESTRICTED */ -+ break; -+ default: -+ break; -+ } -+ } -+} -+ -+static void add_block_index(struct sltg_typelib *sltg, void *data, int size, int index) -+{ -+ struct sltg_block *block = xmalloc(sizeof(*block)); -+ -+ block->length = size; -+ block->data = data; -+ block->index_string = index; -+ block->next = NULL; -+ -+ if (sltg->blocks) -+ { -+ struct sltg_block *blocks = sltg->blocks; -+ -+ while (blocks->next) -+ blocks = blocks->next; -+ -+ blocks->next = block; -+ } -+ else -+ sltg->blocks = block; -+ -+ sltg->n_file_blocks++; -+} -+ -+static void add_block(struct sltg_typelib *sltg, void *data, int size, const char *name) -+{ -+ struct sltg_block *block = xmalloc(sizeof(*block)); -+ int index; -+ -+ chat("add_block: %p,%d,\"%s\"\n", data, size, name); -+ -+ index = add_index(&sltg->index, name); -+ -+ add_block_index(sltg, data, size, index); -+} -+ -+static void *create_library_block(struct sltg_typelib *typelib, int *size, int *index) -+{ -+ void *block; -+ short *p; -+ -+ *size = sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID); -+ if (typelib->library.helpstring) *size += strlen(typelib->library.helpstring); -+ if (typelib->library.helpfile) *size += strlen(typelib->library.helpfile); -+ -+ block = xmalloc(*size); -+ p = block; -+ *p++ = 0x51cc; /* magic */ -+ *p++ = 3; /* res02 */ -+ *p++ = typelib->library.name; -+ *p++ = 0xffff; /* res06 */ -+ if (typelib->library.helpstring) -+ { -+ *p++ = strlen(typelib->library.helpstring); -+ strcpy((char *)p, typelib->library.helpstring); -+ p = (short *)((char *)p + strlen(typelib->library.helpstring)); -+ } -+ else -+ *p++ = 0xffff; -+ if (typelib->library.helpfile) -+ { -+ *p++ = strlen(typelib->library.helpfile); -+ strcpy((char *)p, typelib->library.helpfile); -+ p = (short *)((char *)p + strlen(typelib->library.helpfile)); -+ } -+ else -+ *p++ = 0xffff; -+ *(int *)p = typelib->library.helpcontext; -+ p += 2; -+ *p++ = typelib->library.syskind; -+ *p++ = typelib->library.lcid; -+ *(int *)p = 0; /* res12 */ -+ p += 2; -+ *p++ = typelib->library.libflags; -+ *(int *)p = typelib->library.version; -+ p += 2; -+ *(GUID *)p = typelib->library.uuid; -+ -+ *index = add_index(&typelib->index, "dir"); -+ -+ return block; -+} -+ -+static const char *new_index_name(void) -+{ -+ static char name[11] = "0000000000"; -+ static int pos = 0; -+ char *new_name; -+ -+ if (name[pos] == 'Z') -+ { -+ pos++; -+ if (pos > 9) -+ error("too many index names\n"); -+ } -+ -+ name[pos]++; -+ -+ new_name = xmalloc(sizeof(name)); -+ strcpy(new_name, name); -+ return new_name; -+} -+ -+static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int size, const char *name) -+{ -+ struct sltg_block *block = xmalloc(sizeof(*block)); -+ -+ chat("sltg_add_typeinfo: %p,%d,%s\n", data, size, name); -+ -+ block->length = size; -+ block->data = data; -+ block->index_string = 0; -+ block->next = NULL; -+ -+ if (sltg->typeinfo) -+ { -+ struct sltg_block *typeinfo = sltg->typeinfo; -+ -+ while (typeinfo->next) -+ typeinfo = typeinfo->next; -+ -+ typeinfo->next = block; -+ } -+ else -+ sltg->typeinfo = block; -+ -+ sltg->typeinfo_count++; -+ sltg->typeinfo_size += size; -+} -+ -+static void append_data(struct sltg_data *block, const void *data, int size) -+{ -+ int new_size = block->size + size; -+ -+ if (new_size > block->allocated) -+ { -+ block->allocated = max(block->allocated * 2, new_size); -+ block->data = xrealloc(block->data, block->allocated); -+ } -+ -+ memcpy(block->data + block->size, data, size); -+ block->size = new_size; -+} -+ -+static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type) -+{ -+ error("add_module_typeinfo: %s not implemented\n", type->name); -+} -+ -+static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, int kind) -+{ -+ const char *index_name, *other_name; -+ void *block; -+ short *p; -+ int size, helpcontext = 0; -+ GUID guid = { 0 }; -+ const expr_t *expr; -+ -+ index_name = new_index_name(); -+ other_name = new_index_name(); -+ -+ expr = get_attrp(type->attrs, ATTR_HELPCONTEXT); -+ if (expr) helpcontext = expr->cval; -+ -+ p = get_attrp(type->attrs, ATTR_UUID); -+ if (p) guid = *(GUID *)p; -+ -+ size = sizeof(short) * 8 + 10 /* index_name */ * 2 + sizeof(int) + sizeof(GUID); -+ -+ block = xmalloc(size); -+ p = block; -+ *p++ = strlen(index_name); -+ strcpy((char *)p, index_name); -+ p = (short *)((char *)p + strlen(index_name)); -+ *p++ = strlen(other_name); -+ strcpy((char *)p, other_name); -+ p = (short *)((char *)p + strlen(other_name)); -+ *p++ = -1; /* res1a */ -+ *p++ = add_name(typelib, type->name); /* name offset */ -+ *p++ = 0; /* FIXME: helpstring */ -+ *p++ = -1; /* res20 */ -+ *(int *)p = helpcontext; -+ p += 2; -+ *p++ = -1; /* res26 */ -+ *(GUID *)p = guid; -+ p += sizeof(GUID)/2; -+ *p = kind; -+ -+ sltg_add_typeinfo(typelib, block, size, index_name); -+ -+ return index_name; -+} -+ -+static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind, -+ const struct sltg_hrefmap *hrefmap) -+{ -+ ti->magic = 0x0501; -+ ti->href_offset = -1; -+ ti->res06 = -1; -+ ti->res0e = -1; -+ ti->version = get_attrv(type->attrs, ATTR_VERSION); -+ ti->res16 = 0xfffe0000; -+ ti->misc.unknown1 = 0x02; -+ ti->misc.flags = 0; /* FIXME */ -+ ti->misc.unknown2 = 0x02; -+ ti->misc.typekind = kind; -+ ti->res1e = 0; -+ -+ ti->member_offset = sizeof(*ti); -+ -+ if (hrefmap->href_count) -+ { -+ char name[64]; -+ int i, hrefinfo_size; -+ -+ hrefinfo_size = sizeof(struct sltg_hrefinfo); -+ -+ for (i = 0; i < hrefmap->href_count; i++) -+ { -+ sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); -+ hrefinfo_size += 8 + 2 + strlen(name); -+ } -+ -+ ti->href_offset = ti->member_offset; -+ ti->member_offset += hrefinfo_size; -+ } -+} -+ -+static void init_sltg_tail(struct sltg_tail *tail) -+{ -+ tail->cFuncs = 0; -+ tail->cVars = 0; -+ tail->cImplTypes = 0; -+ tail->res06 = 0; -+ tail->funcs_off = -1; -+ tail->vars_off = -1; -+ tail->impls_off = -1; -+ tail->funcs_bytes = -1; -+ tail->vars_bytes = -1; -+ tail->impls_bytes = -1; -+ tail->tdescalias_vt = -1; -+ tail->res16 = -1; -+ tail->res18 = 0; -+ tail->res1a = 0; -+ tail->simple_alias = 0; -+ tail->res1e = 0; -+ tail->cbSizeInstance = 0; -+ tail->cbAlignment = 4; -+ tail->res24 = -1; -+ tail->res26 = -1; -+ tail->cbSizeVft = 0; -+ tail->res2a = -1; -+ tail->res2c = -1; -+ tail->res2e = -1; -+ tail->res30 = -1; -+ tail->res32 = 0; -+ tail->type_bytes = 0; -+} -+ -+static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap) -+{ -+ struct sltg_hrefinfo hrefinfo; -+ char name[64]; -+ int i; -+ -+ if (!hrefmap->href_count) return; -+ -+ hrefinfo.magic = 0xdf; -+ hrefinfo.res01 = 0; -+ hrefinfo.res02 = -1; -+ hrefinfo.res06 = -1; -+ hrefinfo.res0a = -1; -+ hrefinfo.res0e = -1; -+ hrefinfo.res12 = -1; -+ hrefinfo.res16 = -1; -+ hrefinfo.res1a = -1; -+ hrefinfo.res1e = -1; -+ hrefinfo.res22 = -1; -+ hrefinfo.res26 = -1; -+ hrefinfo.res2a = -1; -+ hrefinfo.res2e = -1; -+ hrefinfo.res32 = -1; -+ hrefinfo.res36 = -1; -+ hrefinfo.res3a = -1; -+ hrefinfo.res3e = -1; -+ hrefinfo.res42 = -1; -+ hrefinfo.number = hrefmap->href_count * 8; -+ hrefinfo.res50 = -1; -+ hrefinfo.res52 = 1; -+ hrefinfo.res53 = 0; -+ hrefinfo.resxx = 0xdf; -+ -+ append_data(data, &hrefinfo, offsetof(struct sltg_hrefinfo, res50)); -+ -+ for (i = 0; i < hrefmap->href_count; i++) -+ append_data(data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8); -+ -+ append_data(data, &hrefinfo.res50, 7); -+ -+ for (i = 0; i < hrefmap->href_count; i++) -+ { -+ short len; -+ -+ sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); -+ len = strlen(name); -+ -+ append_data(data, &len, sizeof(len)); -+ append_data(data, name, len); -+ } -+ -+ append_data(data, &hrefinfo.resxx, sizeof(hrefinfo.resxx)); -+} -+ -+static void dump_var_desc(const char *data, int size) -+{ -+ const unsigned char *p = (const unsigned char *)data; -+ int i; -+ -+ if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return; -+ -+ chat("dump_var_desc: size %d bytes\n", size); -+ -+ for (i = 0; i < size; i++) -+ fprintf(stderr, " %02x", *p++); -+ -+ fprintf(stderr, "\n"); -+} -+ -+static int get_element_size(type_t *type) -+{ -+ int vt = get_type_vt(type); -+ -+ switch (vt) -+ { -+ case VT_I1: -+ case VT_UI1: -+ return 1; -+ -+ case VT_INT: -+ case VT_UINT: -+ return /* typelib_kind == SYS_WIN16 ? 2 : */ 4; -+ -+ case VT_UI2: -+ case VT_I2: -+ case VT_BOOL: -+ return 2; -+ -+ case VT_I4: -+ case VT_UI4: -+ case VT_R4: -+ case VT_ERROR: -+ case VT_HRESULT: -+ return 4; -+ -+ case VT_R8: -+ case VT_I8: -+ case VT_UI8: -+ case VT_CY: -+ case VT_DATE: -+ return 8; -+ -+ case VT_DECIMAL: -+ return 16; -+ -+ case VT_PTR: -+ case VT_UNKNOWN: -+ case VT_DISPATCH: -+ case VT_BSTR: -+ case VT_LPSTR: -+ case VT_LPWSTR: -+ return pointer_size; -+ -+ case VT_VOID: -+ return 0; -+ -+ case VT_VARIANT: -+ return pointer_size == 8 ? 24 : 16; -+ -+ case VT_USERDEFINED: -+ return 0; -+ -+ default: -+ error("get_element_size: unrecognized vt %d\n", vt); -+ break; -+ } -+ -+ return 0; -+} -+ -+static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href) -+{ -+ int i, href = -1; -+ -+ for (i = 0; i < hrefmap->href_count; i++) -+ { -+ if (hrefmap->href[i] == typelib_href) -+ { -+ href = i; -+ break; -+ } -+ } -+ -+ if (href == -1) -+ { -+ href = hrefmap->href_count; -+ -+ if (hrefmap->href) -+ hrefmap->href = xrealloc(hrefmap->href, sizeof(*hrefmap->href) * (hrefmap->href_count + 1)); -+ else -+ hrefmap->href = xmalloc(sizeof(*hrefmap->href)); -+ -+ hrefmap->href[hrefmap->href_count] = typelib_href; -+ hrefmap->href_count++; -+ } -+ -+ chat("typelib href %d mapped to local href %d\n", typelib_href, href); -+ -+ return href << 2; -+} -+ -+static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data, type_t *type, short param_flags, -+ short flags, short base_offset, int *size_instance, struct sltg_hrefmap *hrefmap) -+{ -+ short vt, vt_flags, desc_offset; -+ -+ chat("write_var_desc: type %p, type->name %s\n", -+ type, type->name ? type->name : "NULL"); -+ -+ if (is_array(type) && !type_array_is_decl_as_ptr(type)) -+ { -+ int num_dims, elements, array_start, size, array_size; -+ type_t *atype; -+ struct -+ { -+ short cDims; -+ short fFeatures; -+ int cbElements; -+ int cLocks; -+ void *pvData; -+ int bound[2]; -+ } *array; -+ int *bound; -+ short vt_off[2]; -+ -+ elements = 1; -+ num_dims = 0; -+ -+ atype = type; -+ -+ while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) -+ { -+ num_dims++; -+ elements *= type_array_get_dim(atype); -+ -+ atype = type_array_get_element_type(atype); -+ } -+ -+ chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements); -+ -+ array_start = data->size; -+ -+ size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */; -+ array = xmalloc(size); -+ -+ array->cDims = num_dims; -+ array->fFeatures = 0x0004; /* FADF_EMBEDDED */ -+ array->cbElements = get_element_size(atype); -+ array->cLocks = 0; -+ array->pvData = NULL; -+ -+ bound = array->bound; -+ -+ array_size = array->cbElements; -+ atype = type; -+ -+ while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) -+ { -+ bound[0] = type_array_get_dim(atype); -+ array_size *= bound[0]; -+ bound[1] = 0; -+ bound += 2; -+ -+ atype = type_array_get_element_type(atype); -+ } -+ -+ if (size_instance) -+ { -+ *size_instance += array_size; -+ size_instance = NULL; /* don't account for element size */ -+ } -+ -+ append_data(data, array, size); -+ -+ desc_offset = data->size; -+ -+ vt_off[0] = VT_CARRAY; -+ vt_off[1] = array_start + base_offset; -+ append_data(data, vt_off, sizeof(vt_off)); -+ -+ /* fall through to write array element description */ -+ type = atype; -+ } -+ else -+ desc_offset = data->size; -+ -+ vt = get_type_vt(type); -+ -+ if (vt == VT_PTR) -+ { -+ type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type); -+ -+ if (is_ptr(ref)) -+ { -+ chat("write_var_desc: vt VT_PTR | 0x0400 | %04x\n", param_flags); -+ vt = VT_PTR | 0x0400 | param_flags; -+ append_data(data, &vt, sizeof(vt)); -+ write_var_desc(typelib, data, ref, 0, 0, base_offset, size_instance, hrefmap); -+ } -+ else -+ write_var_desc(typelib, data, ref, param_flags, 0x0e00, base_offset, size_instance, hrefmap); -+ return desc_offset; -+ } -+ -+ chat("write_var_desc: vt %d, flags %04x\n", vt, flags); -+ -+ vt_flags = vt | flags | param_flags; -+ append_data(data, &vt_flags, sizeof(vt_flags)); -+ -+ if (vt == VT_USERDEFINED) -+ { -+ short href; -+ -+ while (type->typelib_idx < 0 && type_is_alias(type)) -+ type = type_alias_get_aliasee_type(type); -+ -+ chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n", -+ type, type->name, type_get_type(type), type->typelib_idx); -+ -+ if (type->typelib_idx == -1) -+ { -+ chat("write_var_desc: trying to ref not added type\n"); -+ -+ switch (type_get_type(type)) -+ { -+ case TYPE_STRUCT: -+ add_structure_typeinfo(typelib, type); -+ break; -+ case TYPE_INTERFACE: -+ add_interface_typeinfo(typelib, type); -+ break; -+ case TYPE_ENUM: -+ add_enum_typeinfo(typelib, type); -+ break; -+ case TYPE_UNION: -+ add_union_typeinfo(typelib, type); -+ break; -+ case TYPE_COCLASS: -+ add_coclass_typeinfo(typelib, type); -+ break; -+ default: -+ error("write_var_desc: VT_USERDEFINED - unhandled type %d\n", -+ type_get_type(type)); -+ } -+ } -+ -+ if (type->typelib_idx == -1) -+ error("write_var_desc: trying to ref not added type\n"); -+ -+ href = local_href(hrefmap, type->typelib_idx); -+ chat("write_var_desc: VT_USERDEFINED, local href %d\n", href); -+ -+ append_data(data, &href, sizeof(href)); -+ } -+ -+ if (size_instance) -+ *size_instance += get_element_size(type); -+ -+ return desc_offset; -+} -+ -+static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) -+{ -+ struct sltg_data data, *var_data = NULL; -+ struct sltg_hrefmap hrefmap; -+ const char *index_name; -+ struct sltg_typeinfo_header ti; -+ struct sltg_member_header member; -+ struct sltg_tail tail; -+ int member_offset, var_count = 0, var_data_size = 0, size_instance = 0; -+ short *type_desc_offset = NULL; -+ -+ if (type->typelib_idx != -1) return; -+ -+ chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name); -+ -+ type->typelib_idx = typelib->n_file_blocks; -+ -+ hrefmap.href_count = 0; -+ hrefmap.href = NULL; -+ -+ if (type_struct_get_fields(type)) -+ { -+ int i = 0; -+ var_t *var; -+ -+ var_count = list_count(type_struct_get_fields(type)); -+ -+ var_data = xmalloc(var_count * sizeof(*var_data)); -+ type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset)); -+ -+ LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) -+ { -+ short base_offset; -+ -+ chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n", -+ var, var->name, var->declspec.type, var->declspec.type->name); -+ -+ init_sltg_data(&var_data[i]); -+ -+ base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable); -+ type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->declspec.type, 0, 0, -+ base_offset, &size_instance, &hrefmap); -+ dump_var_desc(var_data[i].data, var_data[i].size); -+ -+ if (var_data[i].size > sizeof(short)) -+ var_data_size += var_data[i].size; -+ i++; -+ } -+ } -+ -+ init_sltg_data(&data); -+ -+ index_name = add_typeinfo_block(typelib, type, TKIND_RECORD); -+ -+ init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap); -+ append_data(&data, &ti, sizeof(ti)); -+ -+ write_hrefmap(&data, &hrefmap); -+ -+ member_offset = data.size; -+ -+ member.res00 = 0x0001; -+ member.res02 = 0xffff; -+ member.res04 = 0x01; -+ member.extra = var_data_size + var_count * sizeof(struct sltg_variable); -+ append_data(&data, &member, sizeof(member)); -+ -+ var_data_size = 0; -+ -+ if (type_struct_get_fields(type)) -+ { -+ int i = 0; -+ short next = member_offset; -+ var_t *var; -+ -+ LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) -+ { -+ struct sltg_variable variable; -+ -+ next += sizeof(variable); -+ -+ variable.magic = 0x2a; /* always write flags to simplify calculations */ -+ variable.name = add_name(typelib, var->name); -+ variable.byte_offs = 0; -+ if (var_data[i].size > sizeof(short)) -+ { -+ variable.flags = 0; -+ var_data_size = next - member_offset + type_desc_offset[i]; -+ variable.type = var_data_size; -+ next += var_data[i].size; -+ } -+ else -+ { -+ variable.flags = 0x02; -+ variable.type = *(short *)var_data[i].data; -+ } -+ variable.next = i < var_count - 1 ? next - member_offset : -1; -+ variable.memid = 0x40000000 + i; -+ variable.helpcontext = -2; /* 0xfffe */ -+ variable.helpstring = -1; -+ variable.varflags = 0; -+ -+ append_data(&data, &variable, sizeof(variable)); -+ if (var_data[i].size > sizeof(short)) -+ append_data(&data, var_data[i].data, var_data[i].size); -+ -+ i++; -+ } -+ } -+ -+ init_sltg_tail(&tail); -+ -+ tail.cVars = var_count; -+ tail.vars_off = 0; -+ tail.vars_bytes = var_data_size; -+ tail.cbSizeInstance = size_instance; -+ tail.type_bytes = data.size - member_offset - sizeof(member); -+ append_data(&data, &tail, sizeof(tail)); -+ -+ add_block(typelib, data.data, data.size, index_name); -+} -+ -+static importinfo_t *find_importinfo(typelib_t *typelib, const char *name) -+{ -+ importlib_t *importlib; -+ -+ LIST_FOR_EACH_ENTRY(importlib, &typelib->importlibs, importlib_t, entry) -+ { -+ int i; -+ -+ for (i = 0; i < importlib->ntypeinfos; i++) -+ { -+ if (!strcmp(name, importlib->importinfos[i].name)) -+ { -+ chat("Found %s in importlib list\n", name); -+ return &importlib->importinfos[i]; -+ } -+ } -+ } -+ -+ return NULL; -+} -+ -+static int get_func_flags(const var_t *func, int *dispid, int *invokekind, int *helpcontext, const char **helpstring) -+{ -+ const attr_t *attr; -+ int flags; -+ -+ *invokekind = 1 /* INVOKE_FUNC */; -+ *helpcontext = -2; -+ *helpstring = NULL; -+ -+ if (!func->attrs) return 0; -+ -+ flags = 0; -+ -+ LIST_FOR_EACH_ENTRY(attr, func->attrs, const attr_t, entry) -+ { -+ expr_t *expr = attr->u.pval; -+ switch(attr->type) -+ { -+ case ATTR_BINDABLE: -+ flags |= 0x4; /* FUNCFLAG_FBINDABLE */ -+ break; -+ case ATTR_DEFAULTBIND: -+ flags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */ -+ break; -+ case ATTR_DEFAULTCOLLELEM: -+ flags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */ -+ break; -+ case ATTR_DISPLAYBIND: -+ flags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */ -+ break; -+ case ATTR_HELPCONTEXT: -+ *helpcontext = expr->u.lval; -+ break; -+ case ATTR_HELPSTRING: -+ *helpstring = attr->u.pval; -+ break; -+ case ATTR_HIDDEN: -+ flags |= 0x40; /* FUNCFLAG_FHIDDEN */ -+ break; -+ case ATTR_ID: -+ *dispid = expr->cval; -+ break; -+ case ATTR_IMMEDIATEBIND: -+ flags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */ -+ break; -+ case ATTR_NONBROWSABLE: -+ flags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */ -+ break; -+ case ATTR_PROPGET: -+ *invokekind = 0x2; /* INVOKE_PROPERTYGET */ -+ break; -+ case ATTR_PROPPUT: -+ *invokekind = 0x4; /* INVOKE_PROPERTYPUT */ -+ break; -+ case ATTR_PROPPUTREF: -+ *invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */ -+ break; -+ /* FIXME: FUNCFLAG_FREPLACEABLE */ -+ case ATTR_REQUESTEDIT: -+ flags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */ -+ break; -+ case ATTR_RESTRICTED: -+ flags |= 0x1; /* FUNCFLAG_FRESTRICTED */ -+ break; -+ case ATTR_SOURCE: -+ flags |= 0x2; /* FUNCFLAG_FSOURCE */ -+ break; -+ case ATTR_UIDEFAULT: -+ flags |= 0x200; /* FUNCFLAG_FUIDEFAULT */ -+ break; -+ case ATTR_USESGETLASTERROR: -+ flags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */ -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return flags; -+} -+ -+static int get_param_flags(const var_t *param) -+{ -+ const attr_t *attr; -+ int flags, in, out; -+ -+ if (!param->attrs) return 0; -+ -+ flags = 0; -+ in = out = 0; -+ -+ LIST_FOR_EACH_ENTRY(attr, param->attrs, const attr_t, entry) -+ { -+ switch(attr->type) -+ { -+ case ATTR_IN: -+ in++; -+ break; -+ case ATTR_OUT: -+ out++; -+ break; -+ case ATTR_PARAMLCID: -+ flags |= 0x2000; -+ break; -+ case ATTR_RETVAL: -+ flags |= 0x80; -+ break; -+ default: -+ chat("unhandled param attr %d\n", attr->type); -+ break; -+ } -+ } -+ -+ if (out) -+ { -+ if (in) -+ flags |= 0x8000; -+ else -+ flags |= 0x4000; -+ } -+ else if (!in) -+ flags |= 0xc000; -+ -+ return flags; -+} -+ -+ -+static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, var_t *func, -+ int idx, int dispid, short base_offset, struct sltg_hrefmap *hrefmap) -+{ -+ struct sltg_data ret_data, *arg_data; -+ int arg_count = 0, arg_data_size, optional = 0, defaults = 0, old_size; -+ int funcflags = 0, invokekind = 1 /* INVOKE_FUNC */, helpcontext; -+ const char *helpstring; -+ const var_t *arg; -+ short ret_desc_offset, *arg_desc_offset, arg_offset; -+ struct sltg_function func_desc; -+ -+ chat("add_func_desc: %s, idx %#x, dispid %#x\n", func->name, idx, dispid); -+ -+ old_size = data->size; -+ -+ init_sltg_data(&ret_data); -+ ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->declspec.type), -+ 0, 0, base_offset, NULL, hrefmap); -+ dump_var_desc(ret_data.data, ret_data.size); -+ -+ arg_data_size = 0; -+ arg_offset = base_offset + sizeof(struct sltg_function); -+ -+ if (ret_data.size > sizeof(short)) -+ { -+ arg_data_size += ret_data.size; -+ arg_offset += ret_data.size; -+ } -+ -+ if (type_function_get_args(func->declspec.type)) -+ { -+ int i = 0; -+ -+ arg_count = list_count(type_function_get_args(func->declspec.type)); -+ -+ arg_data = xmalloc(arg_count * sizeof(*arg_data)); -+ arg_desc_offset = xmalloc(arg_count * sizeof(*arg_desc_offset)); -+ -+ arg_offset += arg_count * 2 * sizeof(short); -+ -+ LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry) -+ { -+ const attr_t *attr; -+ short param_flags = get_param_flags(arg); -+ -+ chat("add_func_desc: arg[%d] %p (%s), type %p (%s)\n", -+ i, arg, arg->name, arg->declspec.type, arg->declspec.type->name); -+ -+ init_sltg_data(&arg_data[i]); -+ -+ -+ arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->declspec.type, param_flags, 0, -+ arg_offset, NULL, hrefmap); -+ dump_var_desc(arg_data[i].data, arg_data[i].size); -+ -+ if (arg_data[i].size > sizeof(short)) -+ { -+ arg_data_size += arg_data[i].size; -+ arg_offset += arg_data[i].size;; -+ } -+ -+ i++; -+ -+ if (!arg->attrs) continue; -+ -+ LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry) -+ { -+ if (attr->type == ATTR_DEFAULTVALUE) -+ defaults++; -+ else if(attr->type == ATTR_OPTIONAL) -+ optional++; -+ } -+ } -+ } -+ -+ funcflags = get_func_flags(func, &dispid, &invokekind, &helpcontext, &helpstring); -+ -+ if (base_offset != -1) -+ chat("add_func_desc: flags %#x, dispid %#x, invokekind %d, helpcontext %#x, helpstring %s\n", -+ funcflags, dispid, invokekind, helpcontext, helpstring); -+ -+ func_desc.magic = 0x6c; /* always write flags to simplify calculations */ -+ func_desc.flags = (invokekind << 4) | 0x02; -+ if (idx & 0x80000000) -+ { -+ func_desc.next = -1; -+ idx &= ~0x80000000; -+ } -+ else -+ func_desc.next = base_offset + sizeof(func_desc) + arg_data_size + arg_count * 2 * sizeof(short); -+ func_desc.name = base_offset != -1 ? add_name(typelib, func->name) : -1; -+ func_desc.dispid = dispid; -+ func_desc.helpcontext = helpcontext; -+ func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(typelib, helpstring) : -1; -+ func_desc.arg_off = arg_count ? base_offset + sizeof(func_desc) : -1; -+ func_desc.nacc = (arg_count << 3) | 4 /* CC_STDCALL */; -+ func_desc.retnextopt = (optional << 1); -+ if (ret_data.size > sizeof(short)) -+ { -+ func_desc.rettype = base_offset + sizeof(func_desc) + ret_desc_offset; -+ if (arg_count) -+ func_desc.arg_off += ret_data.size; -+ } -+ else -+ { -+ func_desc.retnextopt |= 0x80; -+ func_desc.rettype = *(short *)ret_data.data; -+ } -+ func_desc.vtblpos = idx * pointer_size; -+ func_desc.funcflags = funcflags; -+ -+ append_data(data, &func_desc, sizeof(func_desc)); -+ -+ arg_offset = base_offset + sizeof(struct sltg_function); -+ -+ if (ret_data.size > sizeof(short)) -+ { -+ append_data(data, ret_data.data, ret_data.size); -+ func_desc.arg_off += ret_data.size; -+ arg_offset += ret_data.size; -+ } -+ -+ if (arg_count) -+ { -+ int i = 0; -+ -+ arg_offset += arg_count * 2 * sizeof(short); -+ -+ LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry) -+ { -+ short name, type_offset; -+ -+ name = base_offset != -1 ? add_name(typelib, arg->name) : -1; -+ -+ if (arg_data[i].size > sizeof(short)) -+ { -+ type_offset = (arg_offset + arg_desc_offset[i]); -+ arg_offset += arg_data[i].size; -+ } -+ else -+ { -+ name |= 1; -+ type_offset = *(short *)arg_data[i].data; -+ } -+ -+ append_data(data, &name, sizeof(name)); -+ append_data(data, &type_offset, sizeof(type_offset)); -+ -+ if (base_offset != -1) -+ chat("add_func_desc: arg[%d] - name %s (%#x), type_offset %#x\n", -+ i, arg->name, name, type_offset); -+ -+ i++; -+ } -+ -+ for (i = 0; i < arg_count; i++) -+ { -+ if (arg_data[i].size > sizeof(short)) -+ append_data(data, arg_data[i].data, arg_data[i].size); -+ } -+ } -+ -+ return data->size - old_size; -+} -+ -+static void write_impl_href(struct sltg_data *data, short href) -+{ -+ struct sltg_impl_info impl_info; -+ -+ impl_info.res00 = 0x004a; -+ impl_info.next = -1; -+ impl_info.res04 = -1; -+ impl_info.impltypeflags = 0; -+ impl_info.res07 = 0x80; -+ impl_info.res08 = 0x0012; -+ impl_info.ref = href; -+ impl_info.res0c = 0x4001; -+ impl_info.res0e = -2; /* 0xfffe */ -+ impl_info.res10 = -1; -+ impl_info.res12 = 0x001d; -+ impl_info.pos = 0; -+ -+ append_data(data, &impl_info, sizeof(impl_info)); -+} -+ -+static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *iface) -+{ -+ const statement_t *stmt_func; -+ importinfo_t *ref_importinfo = NULL; -+ short inherit_href = -1; -+ struct sltg_data data; -+ struct sltg_hrefmap hrefmap; -+ const char *index_name; -+ struct sltg_typeinfo_header ti; -+ struct sltg_member_header member; -+ struct sltg_tail tail; -+ int member_offset, base_offset, func_data_size, i; -+ int func_count, inherited_func_count = 0; -+ int dispid, inherit_level = 0; -+ -+ if (iface->typelib_idx != -1) return; -+ -+ chat("add_interface_typeinfo: type %p, type->name %s\n", iface, iface->name); -+ -+ if (!iface->details.iface) -+ { -+ error("interface %s is referenced but not defined\n", iface->name); -+ return; -+ } -+ -+ if (is_attr(iface->attrs, ATTR_DISPINTERFACE)) -+ { -+ error("support for dispinterface %s is not implemented\n", iface->name); -+ return; -+ } -+ -+ hrefmap.href_count = 0; -+ hrefmap.href = NULL; -+ -+ if (type_iface_get_inherit(iface)) -+ { -+ type_t *inherit; -+ -+ inherit = type_iface_get_inherit(iface); -+ -+ chat("add_interface_typeinfo: inheriting from base interface %s\n", inherit->name); -+ -+ ref_importinfo = find_importinfo(typelib->typelib, inherit->name); -+ -+ if (!ref_importinfo && type_iface_get_inherit(inherit)) -+ add_interface_typeinfo(typelib, inherit); -+ -+ if (ref_importinfo) -+ error("support for imported interfaces is not implemented\n"); -+ -+ inherit_href = local_href(&hrefmap, inherit->typelib_idx); -+ -+ while (inherit) -+ { -+ inherit_level++; -+ inherited_func_count += list_count(type_iface_get_stmts(inherit)); -+ inherit = type_iface_get_inherit(inherit); -+ } -+ } -+ -+ /* check typelib_idx again, it could have been added while resolving the parent interface */ -+ if (iface->typelib_idx != -1) return; -+ -+ iface->typelib_idx = typelib->n_file_blocks; -+ -+ /* pass 1: calculate function descriptions data size */ -+ init_sltg_data(&data); -+ -+ STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) -+ { -+ add_func_desc(typelib, &data, stmt_func->u.var, -1, -1, -1, &hrefmap); -+ } -+ -+ func_data_size = data.size; -+ -+ /* pass 2: write function descriptions */ -+ init_sltg_data(&data); -+ -+ func_count = list_count(type_iface_get_stmts(iface)); -+ -+ index_name = add_typeinfo_block(typelib, iface, TKIND_INTERFACE); -+ -+ init_typeinfo(&ti, iface, TKIND_INTERFACE, &hrefmap); -+ append_data(&data, &ti, sizeof(ti)); -+ -+ write_hrefmap(&data, &hrefmap); -+ -+ member_offset = data.size; -+ base_offset = 0; -+ -+ member.res00 = 0x0001; -+ member.res02 = 0xffff; -+ member.res04 = 0x01; -+ member.extra = func_data_size; -+ if (inherit_href != -1) -+ { -+ member.extra += sizeof(struct sltg_impl_info); -+ base_offset += sizeof(struct sltg_impl_info); -+ } -+ append_data(&data, &member, sizeof(member)); -+ -+ if (inherit_href != -1) -+ write_impl_href(&data, inherit_href); -+ -+ i = 0; -+ dispid = 0x60000000 | (inherit_level << 16); -+ -+ STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) -+ { -+ int idx = inherited_func_count + i; -+ -+ if (i == func_count - 1) idx |= 0x80000000; -+ -+ base_offset += add_func_desc(typelib, &data, stmt_func->u.var, -+ idx, dispid + i, base_offset, &hrefmap); -+ i++; -+ } -+ -+ init_sltg_tail(&tail); -+ -+ tail.cFuncs = func_count; -+ tail.funcs_off = 0; -+ tail.funcs_bytes = func_data_size; -+ tail.cbSizeInstance = pointer_size; -+ tail.cbAlignment = pointer_size; -+ tail.cbSizeVft = (inherited_func_count + func_count) * pointer_size; -+ tail.type_bytes = data.size - member_offset - sizeof(member); -+ tail.res24 = 0; -+ tail.res26 = 0; -+ if (inherit_href != -1) -+ { -+ tail.cImplTypes++; -+ tail.impls_off = 0; -+ tail.impls_bytes = 0; -+ -+ tail.funcs_off += sizeof(struct sltg_impl_info); -+ } -+ append_data(&data, &tail, sizeof(tail)); -+ -+ add_block(typelib, data.data, data.size, index_name); -+} -+ -+static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type) -+{ -+ error("add_enum_typeinfo: %s not implemented\n", type->name); -+} -+ -+static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type) -+{ -+ error("add_union_typeinfo: %s not implemented\n", type->name); -+} -+ -+static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type) -+{ -+ error("add_coclass_typeinfo: %s not implemented\n", type->name); -+} -+ -+static void add_type_typeinfo(struct sltg_typelib *typelib, type_t *type) -+{ -+ chat("add_type_typeinfo: adding %s, type %d\n", type->name, type_get_type(type)); -+ -+ switch (type_get_type(type)) -+ { -+ case TYPE_INTERFACE: -+ add_interface_typeinfo(typelib, type); -+ break; -+ case TYPE_STRUCT: -+ add_structure_typeinfo(typelib, type); -+ break; -+ case TYPE_ENUM: -+ add_enum_typeinfo(typelib, type); -+ break; -+ case TYPE_UNION: -+ add_union_typeinfo(typelib, type); -+ break; -+ case TYPE_COCLASS: -+ add_coclass_typeinfo(typelib, type); -+ break; -+ case TYPE_BASIC: -+ case TYPE_POINTER: -+ break; -+ default: -+ error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type), type->name); -+ break; -+ } -+} -+ -+static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt) -+{ -+ switch(stmt->type) -+ { -+ case STMT_LIBRARY: -+ case STMT_IMPORT: -+ case STMT_PRAGMA: -+ case STMT_CPPQUOTE: -+ case STMT_DECLARATION: -+ /* not included in typelib */ -+ break; -+ case STMT_IMPORTLIB: -+ /* not processed here */ -+ break; -+ -+ case STMT_TYPEDEF: -+ { -+ const type_list_t *type_entry = stmt->u.type_list; -+ for (; type_entry; type_entry = type_entry->next) -+ { -+ /* in old style typelibs all types are public */ -+ add_type_typeinfo(typelib, type_entry->type); -+ } -+ break; -+ } -+ -+ case STMT_MODULE: -+ add_module_typeinfo(typelib, stmt->u.type); -+ break; -+ -+ case STMT_TYPE: -+ case STMT_TYPEREF: -+ { -+ type_t *type = stmt->u.type; -+ add_type_typeinfo(typelib, type); -+ break; -+ } -+ -+ default: -+ error("add_statement: unhandled statement type %d\n", stmt->type); -+ break; -+ } -+} -+ -+static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_start) -+{ -+ char pad[0x40]; -+ struct sltg_header -+ { -+ int magic; -+ short n_file_blocks; -+ short res06; -+ short size_of_index; -+ short first_blk; -+ GUID uuid; -+ int res1c; -+ int res20; -+ } header; -+ struct sltg_block_entry -+ { -+ int length; -+ short index_string; -+ short next; -+ } entry; -+ struct sltg_block *block; -+ int i; -+ -+ header.magic = 0x47544c53; -+ header.n_file_blocks = sltg->n_file_blocks + 1; -+ header.res06 = 9; -+ header.size_of_index = sltg->index.size; -+ header.first_blk = 1; -+ header.uuid = sltg_library_guid; -+ header.res1c = 0x00000044; -+ header.res20 = 0xffff0000; -+ -+ put_data(&header, sizeof(header)); -+ -+ block = sltg->blocks; -+ for (i = 0; i < sltg->n_file_blocks - 1; i++) -+ { -+ assert(block->next != NULL); -+ -+ entry.length = block->length; -+ entry.index_string = block->index_string; -+ entry.next = header.first_blk + i + 1; -+ chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n", -+ i, entry.length, entry.index_string, entry.next); -+ put_data(&entry, sizeof(entry)); -+ -+ block = block->next; -+ } -+ -+ assert(block->next == NULL); -+ -+ /* library block length includes helpstrings and name table */ -+ entry.length = block->length + 0x40 + 2 + sltg->typeinfo_size + 4 + 6 + 12 + 0x200 + sltg->name_table.size + 12; -+ entry.index_string = block->index_string; -+ entry.next = 0; -+ chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n", -+ i, entry.length, entry.index_string, entry.next); -+ put_data(&entry, sizeof(entry)); -+ -+ chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size); -+ put_data(sltg->index.data, sltg->index.size); -+ memset(pad, 0, 9); -+ put_data(pad, 9); -+ -+ block = sltg->blocks; -+ for (i = 0; i < sltg->n_file_blocks - 1; i++) -+ { -+ chat("sltg_write_header: writing block %d: %d bytes\n", i, block->length); -+ -+ put_data(block->data, block->length); -+ block = block->next; -+ } -+ -+ assert(block->next == NULL); -+ -+ /* library block */ -+ chat("library_block_start = %#lx\n", (SIZE_T)output_buffer_pos); -+ *library_block_start = output_buffer_pos; -+ chat("sltg_write_header: writing library block %d: %d bytes\n", i, block->length); -+ put_data(block->data, block->length); -+ -+ chat("sltg_write_header: writing pad 0x40 bytes\n"); -+ memset(pad, 0xff, 0x40); -+ put_data(pad, 0x40); -+} -+ -+static void sltg_write_typeinfo(struct sltg_typelib *typelib) -+{ -+ int i; -+ struct sltg_block *block; -+ short count = typelib->typeinfo_count; -+ -+ put_data(&count, sizeof(count)); -+ -+ block = typelib->typeinfo; -+ for (i = 0; i < typelib->typeinfo_count; i++) -+ { -+ chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, block->length); -+ -+ put_data(block->data, block->length); -+ block = block->next; -+ } -+ assert(block == NULL); -+} -+ -+static void sltg_write_helpstrings(struct sltg_typelib *typelib) -+{ -+ static const char dummy[6]; -+ -+ chat("sltg_write_helpstrings: writing dummy 6 bytes\n"); -+ -+ put_data(dummy, sizeof(dummy)); -+} -+ -+static void sltg_write_nametable(struct sltg_typelib *typelib) -+{ -+ static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff }; -+ char pad[0x200]; -+ -+ chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size); -+ -+ put_data(dummy, sizeof(dummy)); -+ memset(pad, 0xff, 0x200); -+ put_data(pad, 0x200); -+ put_data(&typelib->name_table.size, sizeof(typelib->name_table.size)); -+ put_data(typelib->name_table.data, typelib->name_table.size); -+} -+ -+static void sltg_write_remainder(void) -+{ -+ static const short dummy1[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff }; -+ static const short dummy2[] = { 0xffff,0xffff,0x0200,0,0,0 }; -+ static const char dummy3[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 }; -+ static const char TYPELIB[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 }; -+ int pad; -+ -+ pad = 0x01ffff01; -+ put_data(&pad, sizeof(pad)); -+ pad = 0; -+ put_data(&pad, sizeof(pad)); -+ -+ put_data(dummy1, sizeof(dummy1)); -+ -+ put_data(&sltg_library_guid, sizeof(sltg_library_guid)); -+ -+ put_data(TYPELIB, sizeof(TYPELIB)); -+ -+ put_data(dummy2, sizeof(dummy2)); -+ put_data(dummy3, sizeof(dummy3)); -+} -+ -+static void save_all_changes(struct sltg_typelib *typelib) -+{ -+ int library_block_start; -+ int *name_table_offset; -+ -+ sltg_write_header(typelib, &library_block_start); -+ sltg_write_typeinfo(typelib); -+ -+ name_table_offset = (int *)(output_buffer + output_buffer_pos); -+ chat("name_table_offset = %#lx\n", (SIZE_T)output_buffer_pos); -+ put_data(&library_block_start, sizeof(library_block_start)); -+ -+ sltg_write_helpstrings(typelib); -+ -+ *name_table_offset = output_buffer_pos - library_block_start; -+ chat("*name_table_offset = %#x\n", *name_table_offset); -+ -+ sltg_write_nametable(typelib); -+ sltg_write_remainder(); -+ -+ if (strendswith(typelib_name, ".res")) /* create a binary resource file */ -+ { -+ char typelib_id[13] = "#1"; -+ -+ expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID); -+ if (expr) -+ sprintf(typelib_id, "#%d", expr->cval); -+ add_output_to_resources("TYPELIB", typelib_id); -+ output_typelib_regscript(typelib->typelib); -+ } -+ else flush_output_buffer(typelib_name); -+} -+ -+int create_sltg_typelib(typelib_t *typelib) -+{ -+ struct sltg_typelib sltg; -+ const statement_t *stmt; -+ void *library_block; -+ int library_block_size, library_block_index; -+ -+ sltg.typelib = typelib; -+ sltg.typeinfo_count = 0; -+ sltg.typeinfo_size = 0; -+ sltg.typeinfo = NULL; -+ sltg.blocks = NULL; -+ sltg.n_file_blocks = 0; -+ sltg.first_block = 1; -+ -+ init_index(&sltg.index); -+ init_name_table(&sltg); -+ init_library(&sltg); -+ -+ library_block = create_library_block(&sltg, &library_block_size, &library_block_index); -+ -+ if (typelib->stmts) -+ LIST_FOR_EACH_ENTRY(stmt, typelib->stmts, const statement_t, entry) -+ add_statement(&sltg, stmt); -+ -+ add_block_index(&sltg, library_block, library_block_size, library_block_index); -+ -+ save_all_changes(&sltg); -+ -+ return 1; -+} diff --git a/scripts/clang-target-wrapper b/scripts/clang-target-wrapper deleted file mode 100755 index 58043e1..0000000 --- a/scripts/clang-target-wrapper +++ /dev/null @@ -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 -# Rafal Kupiec - - -# 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 "$@" diff --git a/scripts/dlltool-wrapper b/scripts/dlltool-wrapper deleted file mode 100755 index 09db3a3..0000000 --- a/scripts/dlltool-wrapper +++ /dev/null @@ -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 -# Rafal Kupiec - - -# 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} "$@" diff --git a/scripts/ld-wrapper b/scripts/ld-wrapper deleted file mode 100755 index 6fa9d39..0000000 --- a/scripts/ld-wrapper +++ /dev/null @@ -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 -# Rafal Kupiec - - -# 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} "$@" diff --git a/scripts/objdump-wrapper b/scripts/objdump-wrapper deleted file mode 100755 index 977551c..0000000 --- a/scripts/objdump-wrapper +++ /dev/null @@ -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 -# Rafal Kupiec - - -# 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 diff --git a/scripts/xtchain.ps1 b/scripts/xtchain.ps1 new file mode 100644 index 0000000..25c2c8d --- /dev/null +++ b/scripts/xtchain.ps1 @@ -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 + +# Get the absolute path to the XTchain +$XTCDIR = (Get-Item -Path ".\").FullName + +# 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 diff --git a/scripts/xtclib b/scripts/xtclib index 29efe73..f54bdf3 100755 --- a/scripts/xtclib +++ b/scripts/xtclib @@ -4,8 +4,20 @@ # FILE: scripts/xtclib # DESCRIPTION: XTchain library # DEVELOPERS: Rafal Kupiec +# Aiken Harris +# Prints XTChain banner +banner() +{ + local XTC_BANNER="XT Toolchain v${XTCVER} for Linux" + + printf "###############################################################################\n\n" + printf "%*s\n\n" $(( (${#XTC_BANNER} + 80) / 2)) "${XTC_BANNER}" + printf "###############################################################################\n\n\n" +} +export -f banner + # Sets the target architecture charch() { @@ -54,51 +66,67 @@ export -f chbuild # Prints help help() { - version - echo "XTChain defines an internal list of commands:" - echo " * charch [arch] - sets the target CPU architecture [aarch64/armv7/i686/amd64]" - echo " * chbuild [type] - sets build type [debug/release]" - echo " * help - prints this message" - echo " * version - prints XTChain and its components version" - echo " * xbuild - builds an application with a Ninja build system" + banner + 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 " * chbuild [type] - sets build type [debug/release]" + echo " * help - prints this message" + echo " * version - prints XTChain and its components version" + echo " * xbuild - builds an application with a Ninja build system" } export -f help # Displays version banner version() { - echo "###############################################################################" - echo "# XT Toolchain v${XTCVER} for Linux #" - echo "# by Rafal Kupiec #" - echo "###############################################################################" - echo - echo - echo "LLVM Compiler Version: $(${XTCDIR}/bin/clang --version | grep 'clang version' | cut -d' ' -f3)" - echo "LLVM Windres Utility Version: $(${XTCDIR}/bin/i686-w64-mingw32-windres -V | cut -d' ' -f6)" - echo "Mingw IDL Compiler Version: $(${XTCDIR}/bin/i686-w64-mingw32-widl -V | grep 'version' | cut -d' ' -f5)" - echo "Wine Message Compiler Version: $(${XTCDIR}/bin/wmc -V | grep 'version' | cut -d' ' -f5)" - echo "Wine Resource Compiler Version: $(${XTCDIR}/bin/wrc --version | grep 'version' | cut -d' ' -f5)" - echo + local XTCHAIN_EXTTOOLS=false + + if [ ! -f ${XTCDIR}/bin/clang ] || [ "$(which clang)" != "${XTCDIR}/bin/clang" ] || [ $(echo ${XTCVER} | grep "min") ]; then + XTCHAIN_EXTTOOLS=true + for TOOL in {clang,clang++,cmake,lld-link,ninja}; do + which ${TOOL} &> /dev/null + if [ $? -ne 0 ]; then + echo "ERROR: You are using minimal version of XTChain and '${TOOL}' has been not found in your system!" + echo "ERROR: Please install all required tools." + exit 1 + fi + 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 "\nLLVM Resource Compiler: $(windres --version | grep version | cut -d' ' -f5) ($(which windres))" + 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} chbuild ${BUILD_TYPE:-DEBUG} - echo - echo + + echo -en "\n\nFor a list of all supported commands, type 'help'" + echo -en "\n-------------------------------------------------\n\n" } export -f version # Builds application (wrapper to Ninja) xbuild() { - if [ ! -f build.arch ]; then - ninja "$@" - else - ARCH=$(cat build.arch) - if [ x"${ARCH}" != x"${TARGET}" ]; then - echo "Build is configured for '${ARCH}' while current target set to '${TARGET}'!" - echo "Cannot continue until conflict is resolved ..." - return 1 - fi - ninja "$@" - fi + if [ ! -f build.arch ]; then + ninja "$@" + else + ARCH=$(cat build.arch) + if [ x"${ARCH}" != x"${TARGET}" ]; then + echo "Build is configured for '${ARCH}' while current target set to '${TARGET}'!" + echo "Cannot continue until conflict is resolved ..." + return 1 + fi + ninja "$@" + fi } export -f xbuild diff --git a/scripts/xtclib.ps1 b/scripts/xtclib.ps1 new file mode 100644 index 0000000..c8a7a88 --- /dev/null +++ b/scripts/xtclib.ps1 @@ -0,0 +1,148 @@ +# PROJECT: XTchain +# LICENSE: See the COPYING.md in the top level directory +# FILE: scripts/xtclib.ps1 +# DESCRIPTION: XTchain library +# DEVELOPERS: Aiken Harris + + +# 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 "LLVM Resource Compiler: $(windres --version | Select-String -Pattern "version (\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command windres).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 { + param( + [string[]]$args + ) + + 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 + } +} diff --git a/tools/windres.c b/tools/windres.c deleted file mode 100644 index f560875..0000000 --- a/tools/windres.c +++ /dev/null @@ -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 - * Martin Storsjo - * Rafal Kupiec - */ - -#include "xtchain.h" - -#define WINDRES_VERSION "1.0" - -#ifndef DEFAULT_TARGET -#define DEFAULT_TARGET "x86_64-w64-mingw32" -#endif - -#include - -#define _tspawnvp_escape _spawnvp - -#include -#include - -#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