Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[build]
target = "x86_64-pc-windows-msvc"

[target.x86_64-pc-windows-msvc]
linker = "./.cargo/lld-link-winegcc"
rustflags = [
"-Lnative=./.cargo/wine-msvc-libs",
]

[env]
CC_x86_64_pc_windows_msvc = "/usr/local/bin/winegcc --target=x86_64-windows-msvc"
CXX_x86_64_pc_windows_msvc = "/usr/local/bin/wineg++ --target=x86_64-windows-msvc"
AR_x86_64_pc_windows_msvc = "/usr/local/bin/llvm-lib"
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_AR = "/usr/local/bin/llvm-lib"
92 changes: 92 additions & 0 deletions .cargo/lld-link-winegcc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/bin/zsh
set -euo pipefail

script_dir=${0:A:h}
repo_root=${script_dir:h}
shim_dir="$script_dir/wine-shims"

mkdir -p "$shim_dir"

source "$repo_root/.env" || :

clang --target=x86_64-windows-msvc -c "$shim_dir/tls_shim.c" -o "$shim_dir/tls_shim.obj"
clang++ --target=x86_64-windows-msvc -fno-exceptions -fno-rtti -nostdinc++ -nostdlib++ \
-c "$shim_dir/typeinfo_shim.cpp" -o "$shim_dir/typeinfo_shim.obj"

typeset -a out_args
typeset -A skipped_defaultlibs

for arg in "$@"; do
case "$arg" in
-flavor|link)
;;
/OUT:*)
out_args+=("-o" "${arg#/OUT:}")
;;
/LIBPATH:*|/libpath:*)
out_args+=("-L${arg#*:}")
;;
/defaultlib:msvcrt)
if [[ -z ${skipped_defaultlibs[msvcrt]-} ]]; then
out_args+=("-lmsvcrt")
fi
;;
/NODEFAULTLIB:*|/nodefaultlib:*)
lib_name=${arg#*:}
lib_name=${lib_name:l}
skipped_defaultlibs[$lib_name]=1
if [[ "$lib_name" == "msvcrt" ]]; then
filtered_args=()
for existing in "${out_args[@]}"; do
if [[ "$existing" != "-lmsvcrt" ]]; then
filtered_args+=("$existing")
fi
done
out_args=("${filtered_args[@]}")
out_args+=("-nostartfiles" "-nostdlib")
fi
out_args+=("-Xlinker" "$arg")
;;
/defaultlib:*.lib|/DEFAULTLIB:*.lib)
lib_name=${arg#*:}
lib_name=${lib_name:t}
lib_name=${lib_name%.lib}
out_args+=("-l${lib_name}")
;;
/defaultlib:*)
lib_name=${arg#*:}
out_args+=("-l${lib_name}")
;;
winecrt0.lib)
out_args+=("-lwinecrt0")
;;
/DLL)
out_args+=("-shared")
;;
/DEF:*|/IMPLIB:*|/ENTRY:*|/SUBSYSTEM:*|/FIXED:*|/DYNAMICBASE|/NOLOGO|/NXCOMPAT|/OPT:*|/DEBUG|/PDBALTPATH:*|/NATVIS:*|/linkrepro:*)
# These are real lld-link options. Keep them as linker args instead of
# translating them ourselves.
out_args+=("-Xlinker" "$arg")
;;
[A-Za-z0-9_]*.lib)
lib_name=${arg%.lib}
out_args+=("-l${lib_name}")
;;
*.lib|*.o|*.obj|*.rlib)
out_args+=("$arg")
;;
*)
out_args+=("$arg")
;;
esac
done

if [[ -z ${skipped_defaultlibs[msvcrt]-} ]]; then
out_args=("$shim_dir/tls_shim.obj" "$shim_dir/typeinfo_shim.obj" "${out_args[@]}")
fi

if [[ -n ${skipped_defaultlibs[msvcrt]-} ]]; then
exec clang --target=x86_64-windows-msvc -fuse-ld=lld-link "${out_args[@]}"
fi

exec winegcc --target=x86_64-windows-msvc "${out_args[@]}"
1 change: 1 addition & 0 deletions .cargo/wine-msvc-libs/dbghelp.lib
1 change: 1 addition & 0 deletions .cargo/wine-msvc-libs/kernel32.lib
1 change: 1 addition & 0 deletions .cargo/wine-msvc-libs/msvcrt.lib
1 change: 1 addition & 0 deletions .cargo/wine-msvc-libs/ntdll.lib
1 change: 1 addition & 0 deletions .cargo/wine-msvc-libs/userenv.lib
1 change: 1 addition & 0 deletions .cargo/wine-msvc-libs/winecrt0.lib
1 change: 1 addition & 0 deletions .cargo/wine-msvc-libs/ws2_32.lib
1 change: 1 addition & 0 deletions .cargo/wine-shims/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.obj
25 changes: 25 additions & 0 deletions .cargo/wine-shims/tls_shim.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifdef _WIN64
typedef unsigned long ULONG;

int _tls_index = 0;

__attribute__((section(".tls"))) char _tls_start = 0;
__attribute__((section(".tls$ZZZ"))) char _tls_end = 0;

__attribute__((section(".CRT$XLA"))) void *__xl_a = 0;
__attribute__((section(".CRT$XLZ"))) void *__xl_z = 0;

const struct {
void *StartAddressOfRawData;
void *EndAddressOfRawData;
void *AddressOfIndex;
void *AddressOfCallBacks;
ULONG SizeOfZeroFill;
ULONG Characteristics;
} _tls_used = {
&_tls_start,
&_tls_end,
&_tls_index,
&__xl_a + 1,
};
#endif
43 changes: 43 additions & 0 deletions .cargo/wine-shims/typeinfo_shim.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
extern "C" int strcmp(const char*, const char*);
extern "C" void free(void*);

class type_info {
type_info& operator=(const type_info&);
type_info(const type_info&);

mutable struct {
const char* undecorated_name;
const char decorated_name[1];
} data;

int compare(const type_info& rhs) const noexcept;

public:
virtual ~type_info();

const char* name() const noexcept;
unsigned long long hash_code() const noexcept;
};

type_info::type_info(const type_info&) = default;

int type_info::compare(const type_info& rhs) const noexcept {
if (&data == &rhs.data) {
return 0;
}
return strcmp(&data.decorated_name[1], &rhs.data.decorated_name[1]);
}

const char* type_info::name() const noexcept {
return &data.decorated_name[1];
}

unsigned long long type_info::hash_code() const noexcept {
return 0;
}

type_info::~type_info() {}

void operator delete(void* p, unsigned long long) noexcept {
free(p);
}