Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasm: no longer compile my project #4324

Closed
ryuukk opened this issue Feb 23, 2023 · 13 comments
Closed

wasm: no longer compile my project #4324

ryuukk opened this issue Feb 23, 2023 · 13 comments
Labels
B-webassembly WASM-related

Comments

@ryuukk
Copy link
Contributor

ryuukk commented Feb 23, 2023

OS: Windows 10 x64
$ ldc2 --version
LDC - the LLVM D compiler (1.31.0):
  based on DMD v2.101.2 and LLVM 14.0.3
  built with LDC - the LLVM D compiler (1.31.0)
  Default target: x86_64-pc-windows-msvc
  Host CPU: skylake
  http://dlang.org - http://wiki.dlang.org/LDC

Hello,

My project no longer build for wasm, i'm not sure i understand why, i made sure no code import modules from libc that isn't in its proper version block for platform specific code

I get the following:

https://gist.github.com/ryuukk/c14e8152b1071baa2ce6fba5f9d11290

How should i debug this?

Why doesn't the compiler tell me what imports it?

Why does the compiler compile code that i supposedly do not use/import?

@kinke
Copy link
Member

kinke commented Feb 24, 2023

This is a failure to compile the dub_platform_probe module, something dub does implicitly to probe the compiler for the target platform. See https://github.com/dlang/dub/blob/9b15ad07e1f0731cd95c72e9d2119ebdac3d771d/source/dub/compilers/utils.d#L317-L363 for its source; seems like it's not compatible with what you set up in your ldc2.conf. Running dub with --vverbose (IIRC) might show more details.

@ryuukk
Copy link
Contributor Author

ryuukk commented Feb 24, 2023

you were right, on a blank file with ldc directly it works, but with dub it doesn't

Here is the output on a blank source file (just _start) with verbose mode:

$  dub build --compiler=ldc2 --arch=wasm32-unknown-unknown-wasm --vverbose
Using dub registry url 'https://code.dlang.org/'
Note: Failed to determine version of package test at .. Assuming ~master.
Error Failed to invoke the compiler ldc2 to determine the build platform: binary    C:\D\ldc2\bin\ldc2.exe
version   1.31.0 (DMD v2.101.2, LLVM 14.0.3)
config    C:\D\ldc2\etc\ldc2.conf (wasm32-unknown-unknown-wasm)
predefs   LDC all D_Version2 assert D_PreConditions D_PostConditions D_Invariants D_ModuleInfo D_Exceptions D_TypeInfo WebAssembly LittleEndian FreeStanding LDC_LLVM_1400
parse     dub_platform_probe_089b65e3_594f_4193_a820_02e334021449
importall dub_platform_probe
import    object        (C:\D\ldc2\bin\..\import\object.d)
import    core.internal.hash    (C:\D\ldc2\bin\..\import\core\internal\hash.d)
import    core.internal.traits  (C:\D\ldc2\bin\..\import\core\internal\traits.d)
import    core.internal.entrypoint      (C:\D\ldc2\bin\..\import\core\internal\entrypoint.d)
import    core.internal.array.appending (C:\D\ldc2\bin\..\import\core\internal\array\appending.d)
import    core.internal.array.comparison        (C:\D\ldc2\bin\..\import\core\internal\array\comparison.d)
import    core.internal.array.equality  (C:\D\ldc2\bin\..\import\core\internal\array\equality.d)
import    core.internal.array.casting   (C:\D\ldc2\bin\..\import\core\internal\array\casting.d)
import    core.internal.array.concatenation     (C:\D\ldc2\bin\..\import\core\internal\array\concatenation.d)
import    core.internal.array.construction      (C:\D\ldc2\bin\..\import\core\internal\array\construction.d)
import    core.internal.array.arrayassign       (C:\D\ldc2\bin\..\import\core\internal\array\arrayassign.d)
import    core.internal.array.capacity  (C:\D\ldc2\bin\..\import\core\internal\array\capacity.d)
import    core.internal.dassert (C:\D\ldc2\bin\..\import\core\internal\dassert.d)
import    core.atomic   (C:\D\ldc2\bin\..\import\core\atomic.d)
import    core.internal.attributes      (C:\D\ldc2\bin\..\import\core\internal\attributes.d)
import    core.internal.atomic  (C:\D\ldc2\bin\..\import\core\internal\atomic.d)
import    ldc.intrinsics        (C:\D\ldc2\bin\..\import\ldc\intrinsics.di)
import    core.internal.destruction     (C:\D\ldc2\bin\..\import\core\internal\destruction.d)
import    core.internal.moving  (C:\D\ldc2\bin\..\import\core\internal\moving.d)
import    core.internal.postblit        (C:\D\ldc2\bin\..\import\core\internal\postblit.d)
import    core.internal.switch_ (C:\D\ldc2\bin\..\import\core\internal\switch_.d)
import    core.lifetime (C:\D\ldc2\bin\..\import\core\lifetime.d)
import    core.builtins (C:\D\ldc2\bin\..\import\core\builtins.d)
semantic  dub_platform_probe
import    core.stdc.string      (C:\D\ldc2\bin\..\import\core\stdc\string.d)
import    core.internal.array.utils     (C:\D\ldc2\bin\..\import\core\internal\array\utils.d)
import    core.memory   (C:\D\ldc2\bin\..\import\core\memory.d)
import    core.stdc.errno       (C:\D\ldc2\bin\..\import\core\stdc\errno.d)
import    core.time     (C:\D\ldc2\bin\..\import\core\time.d)
import    core.exception        (C:\D\ldc2\bin\..\import\core\exception.d)
import    core.stdc.time        (C:\D\ldc2\bin\..\import\core\stdc\time.d)
import    core.stdc.config      (C:\D\ldc2\bin\..\import\core\stdc\config.d)
import    core.stdc.stdio       (C:\D\ldc2\bin\..\import\core\stdc\stdio.d)
import    core.stdc.stdint      (C:\D\ldc2\bin\..\import\core\stdc\stdint.d)
import    core.stdc.stddef      (C:\D\ldc2\bin\..\import\core\stdc\stddef.d)
import    core.stdc.signal      (C:\D\ldc2\bin\..\import\core\stdc\signal.d)
import    core.stdc.wchar_      (C:\D\ldc2\bin\..\import\core\stdc\wchar_.d)
import    core.stdc.stdarg      (C:\D\ldc2\bin\..\import\core\stdc\stdarg.d)
import    core.internal.string  (C:\D\ldc2\bin\..\import\core\internal\string.d)
C:\D\ldc2\bin\..\import\core\stdc\time.d(33): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(33): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(35): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(35): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(37): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(37): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(40): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(42): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(44): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(44): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(46): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(46): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(48): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(128): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(172): Error: undefined identifier `FILE`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(172): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(174): Error: undefined identifier `FILE`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(174): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(176): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(176): Error: undefined identifier `wchar_t`, did you mean `dchar`?

Full exception: dub.compilers.compiler.CompilerInvocationException@source\dub\compilers\compiler.d(189): Failed to invoke the compiler ldc2 to determine the build platform: binary    C:\D\ldc2\bin\ldc2.exe
version   1.31.0 (DMD v2.101.2, LLVM 14.0.3)
config    C:\D\ldc2\etc\ldc2.conf (wasm32-unknown-unknown-wasm)
predefs   LDC all D_Version2 assert D_PreConditions D_PostConditions D_Invariants D_ModuleInfo D_Exceptions D_TypeInfo WebAssembly LittleEndian FreeStanding LDC_LLVM_1400
parse     dub_platform_probe_089b65e3_594f_4193_a820_02e334021449
importall dub_platform_probe
import    object        (C:\D\ldc2\bin\..\import\object.d)
import    core.internal.hash    (C:\D\ldc2\bin\..\import\core\internal\hash.d)
import    core.internal.traits  (C:\D\ldc2\bin\..\import\core\internal\traits.d)
import    core.internal.entrypoint      (C:\D\ldc2\bin\..\import\core\internal\entrypoint.d)
import    core.internal.array.appending (C:\D\ldc2\bin\..\import\core\internal\array\appending.d)
import    core.internal.array.comparison        (C:\D\ldc2\bin\..\import\core\internal\array\comparison.d)
import    core.internal.array.equality  (C:\D\ldc2\bin\..\import\core\internal\array\equality.d)
import    core.internal.array.casting   (C:\D\ldc2\bin\..\import\core\internal\array\casting.d)
import    core.internal.array.concatenation     (C:\D\ldc2\bin\..\import\core\internal\array\concatenation.d)
import    core.internal.array.construction      (C:\D\ldc2\bin\..\import\core\internal\array\construction.d)
import    core.internal.array.arrayassign       (C:\D\ldc2\bin\..\import\core\internal\array\arrayassign.d)
import    core.internal.array.capacity  (C:\D\ldc2\bin\..\import\core\internal\array\capacity.d)
import    core.internal.dassert (C:\D\ldc2\bin\..\import\core\internal\dassert.d)
import    core.atomic   (C:\D\ldc2\bin\..\import\core\atomic.d)
import    core.internal.attributes      (C:\D\ldc2\bin\..\import\core\internal\attributes.d)
import    core.internal.atomic  (C:\D\ldc2\bin\..\import\core\internal\atomic.d)
import    ldc.intrinsics        (C:\D\ldc2\bin\..\import\ldc\intrinsics.di)
import    core.internal.destruction     (C:\D\ldc2\bin\..\import\core\internal\destruction.d)
import    core.internal.moving  (C:\D\ldc2\bin\..\import\core\internal\moving.d)
import    core.internal.postblit        (C:\D\ldc2\bin\..\import\core\internal\postblit.d)
import    core.internal.switch_ (C:\D\ldc2\bin\..\import\core\internal\switch_.d)
import    core.lifetime (C:\D\ldc2\bin\..\import\core\lifetime.d)
import    core.builtins (C:\D\ldc2\bin\..\import\core\builtins.d)
semantic  dub_platform_probe
import    core.stdc.string      (C:\D\ldc2\bin\..\import\core\stdc\string.d)
import    core.internal.array.utils     (C:\D\ldc2\bin\..\import\core\internal\array\utils.d)
import    core.memory   (C:\D\ldc2\bin\..\import\core\memory.d)
import    core.stdc.errno       (C:\D\ldc2\bin\..\import\core\stdc\errno.d)
import    core.time     (C:\D\ldc2\bin\..\import\core\time.d)
import    core.exception        (C:\D\ldc2\bin\..\import\core\exception.d)
import    core.stdc.time        (C:\D\ldc2\bin\..\import\core\stdc\time.d)
import    core.stdc.config      (C:\D\ldc2\bin\..\import\core\stdc\config.d)
import    core.stdc.stdio       (C:\D\ldc2\bin\..\import\core\stdc\stdio.d)
import    core.stdc.stdint      (C:\D\ldc2\bin\..\import\core\stdc\stdint.d)
import    core.stdc.stddef      (C:\D\ldc2\bin\..\import\core\stdc\stddef.d)
import    core.stdc.signal      (C:\D\ldc2\bin\..\import\core\stdc\signal.d)
import    core.stdc.wchar_      (C:\D\ldc2\bin\..\import\core\stdc\wchar_.d)
import    core.stdc.stdarg      (C:\D\ldc2\bin\..\import\core\stdc\stdarg.d)
import    core.internal.string  (C:\D\ldc2\bin\..\import\core\internal\string.d)
C:\D\ldc2\bin\..\import\core\stdc\time.d(33): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(33): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(35): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(35): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(37): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(37): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(40): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(42): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(44): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(44): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(46): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(46): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(48): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(128): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(172): Error: undefined identifier `FILE`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(172): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(174): Error: undefined identifier `FILE`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(174): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(176): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(176): Error: undefined identifier `wchar_t`, did you mean `dchar`?

----------------
0x00007FF6DF7B6187
0x00007FF6DF3EE179
0x00007FF6DF3EE072
0x00007FF6DF52C547
0x00007FF6DF535AD7
0x00007FF6DF33BB4E
0x00007FF6DF33B7C9
0x00007FF6DF33CFF0
0x00007FF6DF33DCD7
0x00007FF6DF337536
0x00007FF6DF321528
0x00007FF6DF7D8433
0x00007FF6DF7D828F
0x00007FF6DF7D838F
0x00007FF6DF7D828F
0x00007FF6DF7D81A0
0x00007FF6DF7AC2F9
0x00007FF6DF323C12
0x00007FF6DF847EF0
0x00007FFFD75174B4 in BaseThreadInitThunk
0x00007FFFD93E26A1 in RtlUserThreadStart

I downloaded: ldc2-1.31.0-windows-multilib

Here is the ldc2.conf

// See comments in driver/config.d in ldc source tree for grammar description of
// this config file.

// For cross-compilation, you can add sections for specific target triples by
// naming the sections as (quoted) regex patterns. See LDC's `-v` output
// (`config` line) to figure out your normalized triple, depending on the used
// `-mtriple`, `-m32` etc. E.g.:
//
//     "^arm.*-linux-gnueabihf$": { … };
//     "86(_64)?-.*-linux": { … };
//     "i[3-6]86-.*-windows-msvc": { … };
//
// Later sections take precedence and override settings from previous matching
// sections while inheriting unspecified settings from previous sections.
// A `default` section always matches (treated as ".*") and is therefore usually
// the first section.
default:
{
    // default switches injected before all explicit command-line switches
    switches = [
        "-defaultlib=phobos2-ldc,druntime-ldc",
    ];
    // default switches appended after all explicit command-line switches
    post-switches = [
        "-I%%ldcbinarypath%%/../import",
    ];
    // default directories to be searched for libraries when linking
    lib-dirs = [
        "%%ldcbinarypath%%/../lib64",
    ];
    // default rpath when linking against the shared default libs
    rpath = "%%ldcbinarypath%%/../lib64";
};

"^wasm(32|64)-":
{
    switches = [
        "-defaultlib=",
        "-L-z", "-Lstack-size=1048576",
        "-L--stack-first",
        "-link-internally",
        "-L--export-dynamic",
    ];
    lib-dirs = [];
};

"i[3-6]86-.*-windows-msvc":
{
    // default switches injected before all explicit command-line switches
    switches = [
        "-defaultlib=phobos2-ldc,druntime-ldc",
    ];
    // default switches appended after all explicit command-line switches
    post-switches = [
        "-I%%ldcbinarypath%%/../import",
    ];
    // default directories to be searched for libraries when linking
    lib-dirs = [
        "%%ldcbinarypath%%/../lib32",
    ];
    // default rpath when linking against the shared default libs
    rpath = "%%ldcbinarypath%%/../lib32";
};

@kinke
Copy link
Member

kinke commented Feb 24, 2023

You'd need to get hold of the temp .d file being compiled (with -mtriple=… for wasm) if dub really doesn't print it in its logs (and doesn't even show the cmdline apparently); that'd be some dub_platform_probe_089b65e3_594f_4193_a820_02e334021449.d file somewhere in your filesystem (maybe still there, maybe already removed by dub). This file then imports regular druntime/Phobos (inherited post-switches), not your modified version with the wasm fixes.

@ryuukk
Copy link
Contributor Author

ryuukk commented Feb 24, 2023

i haven't modified anything, that's all untouched, i downloaded the compiler from release section and unzipped it

there is no dub_platform_probe file, when i compile the project it gets created but it gets instantly removed so i can't open it

@ryuukk
Copy link
Contributor Author

ryuukk commented Feb 24, 2023

i managed to get it by editing dub code

                module dub_platform_probe;

                template toString(int v) { enum toString = v.stringof; }
                string stringArray(string[] ary) {
                        string res;
                        foreach (i, e; ary) {
                                if (i)
                                        res ~= ", ";
                                res ~= '"' ~ e ~ '"';
                        }
                        return res;
                }

                pragma(msg, `__dub_probe_begin__`
                        ~ '\n' ~ `{`
                        ~ '\n' ~ `  "compiler": "`~ determineCompiler() ~ `",`
                        ~ '\n' ~ `  "frontendVersion": ` ~ toString!__VERSION__ ~ `,`
                        ~ '\n' ~ `  "compilerVendor": "` ~ __VENDOR__ ~ `",`
                        ~ '\n' ~ `  "platform": [`
                        ~ '\n' ~ `    ` ~ determinePlatform().stringArray
                        ~ '\n' ~ `  ],`
                        ~ '\n' ~ `  "architecture": [`
                        ~ '\n' ~ `    ` ~ determineArchitecture().stringArray
                        ~ '\n' ~ `   ],`
                        ~ '\n' ~ `}`
                        ~ '\n' ~ `__dub_probe_end__`);

                string[] determinePlatform() {
        string[] ret;
        version(Windows) ret ~= "windows";
        version(linux) ret ~= "linux";
        version(Posix) ret ~= "posix";
        version(OSX) ret ~= ["osx", "darwin"];
        version(iOS) ret ~= ["ios", "darwin"];
        version(TVOS) ret ~= ["tvos", "darwin"];
        version(WatchOS) ret ~= ["watchos", "darwin"];
        version(FreeBSD) ret ~= "freebsd";
        version(OpenBSD) ret ~= "openbsd";
        version(NetBSD) ret ~= "netbsd";
        version(DragonFlyBSD) ret ~= "dragonflybsd";
        version(BSD) ret ~= "bsd";
        version(Solaris) ret ~= "solaris";
        version(AIX) ret ~= "aix";
        version(Haiku) ret ~= "haiku";
        version(SkyOS) ret ~= "skyos";
        version(SysV3) ret ~= "sysv3";
        version(SysV4) ret ~= "sysv4";
        version(Hurd) ret ~= "hurd";
        version(Android) ret ~= "android";
        version(Cygwin) ret ~= "cygwin";
        version(MinGW) ret ~= "mingw";
        version(PlayStation4) ret ~= "playstation4";
        version(WebAssembly) ret ~= "wasm";
        return ret;
 }
                string[] determineArchitecture() {
        string[] ret;
        version(X86) ret ~= "x86";
        // Hack: see #1535
        // Makes "x86_omf" available as a platform specifier in the package recipe
        version(X86) version(CRuntime_DigitalMars) ret ~= "x86_omf";
        // Hack: see #1059
        // When compiling with --arch=x86_mscoff build_platform.architecture is equal to ["x86"] and canFind below is false.
        // This hack prevents unnecessary warning 'Failed to apply the selected architecture x86_mscoff. Got ["x86"]'.
        // And also makes "x86_mscoff" available as a platform specifier in the package recipe
        version(X86) version(CRuntime_Microsoft) ret ~= "x86_mscoff";
        version(X86_64) ret ~= "x86_64";
        version(ARM) ret ~= "arm";
        version(AArch64) ret ~= "aarch64";
        version(ARM_Thumb) ret ~= "arm_thumb";
        version(ARM_SoftFloat) ret ~= "arm_softfloat";
        version(ARM_HardFloat) ret ~= "arm_hardfloat";
        version(PPC) ret ~= "ppc";
        version(PPC_SoftFP) ret ~= "ppc_softfp";
        version(PPC_HardFP) ret ~= "ppc_hardfp";
        version(PPC64) ret ~= "ppc64";
        version(IA64) ret ~= "ia64";
        version(MIPS) ret ~= "mips";
        version(MIPS32) ret ~= "mips32";
        version(MIPS64) ret ~= "mips64";
        version(MIPS_O32) ret ~= "mips_o32";
        version(MIPS_N32) ret ~= "mips_n32";
        version(MIPS_O64) ret ~= "mips_o64";
        version(MIPS_N64) ret ~= "mips_n64";
        version(MIPS_EABI) ret ~= "mips_eabi";
        version(MIPS_NoFloat) ret ~= "mips_nofloat";
        version(MIPS_SoftFloat) ret ~= "mips_softfloat";
        version(MIPS_HardFloat) ret ~= "mips_hardfloat";
        version(SPARC) ret ~= "sparc";
        version(SPARC_V8Plus) ret ~= "sparc_v8plus";
        version(SPARC_SoftFP) ret ~= "sparc_softfp";
        version(SPARC_HardFP) ret ~= "sparc_hardfp";
        version(SPARC64) ret ~= "sparc64";
        version(S390) ret ~= "s390";
        version(S390X) ret ~= "s390x";
        version(HPPA) ret ~= "hppa";
        version(HPPA64) ret ~= "hppa64";
        version(SH) ret ~= "sh";
        version(SH64) ret ~= "sh64";
        version(Alpha) ret ~= "alpha";
        version(Alpha_SoftFP) ret ~= "alpha_softfp";
        version(Alpha_HardFP) ret ~= "alpha_hardfp";
        return ret;
 }
                string determineCompiler() {
        version(DigitalMars) return "dmd";
        else version(GNU) return "gdc";
        else version(LDC) return "ldc";
        else version(SDC) return "sdc";
        else return null;
 }

still same cmd: dub build --compiler=ldc2 --arch=wasm32-unknown-unknown-wasm --vverbose -f

EDIT:
i was curious, so i tried compile it: $ ldc2 test.d -mtriple=wasm32-unknown-unknown-wasm

and i get:

C:\D\ldc2\bin\..\import\core\stdc\time.d(33): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(33): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(35): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(35): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(37): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(37): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(40): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(42): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(44): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(44): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(46): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\time.d(46): Error: undefined identifier `time_t`, did you mean function `time`?
C:\D\ldc2\bin\..\import\core\stdc\time.d(48): Error: undefined identifier `tm`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(128): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(172): Error: undefined identifier `FILE`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(172): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(174): Error: undefined identifier `FILE`
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(174): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(176): Error: undefined identifier `wchar_t`, did you mean `dchar`?
C:\D\ldc2\bin\..\import\core\stdc\wchar_.d(176): Error: undefined identifier `wchar_t`, did you mean `dchar`?

@kinke
Copy link
Member

kinke commented Feb 24, 2023

Yeah, you'll only be able to use dub if that file can be compiled for your target (with -o-, i.e., no codegen required). And looks like that regressed with D v2.101; I guess due to new templated druntime hooks (edit: so ending up importing more from druntime, incl. modules not ready for wasm yet).

@kinke
Copy link
Member

kinke commented Feb 24, 2023

How should i debug this?

I've used -vcg-ast to dump the produced AST (without -mtriple=wasm32-…). That writes a .cg file next to the source file. And the problem is indeed a new array-append hook:

v1.30 AST:

module dub_platform_probe;
import object;
enum toString(int v) = v.stringof;
string stringArray(string[] ary)
{
	string res = null;
	{
		scope string[] __r3 = ary[];
		ulong __key2 = 0LU;
		for (; __key2 < __r3.length; __key2 += 1LU)
		{
			string e = __r3[__key2];
			ulong i = __key2;
			if (i)
				res ~= ", ";
			res ~= '"' ~ e ~ '"';
		}
	}
	return res;
}
pragma (msg, "__dub_probe_begin__\n{\n  \"compiler\": \"" ~ determineCompiler() ~ "\",\n  \"frontendVersion\": 2100,\n  \"compilerVendor\": \"LDC\",\n  \"platform\": [\n    " ~ stringArray(determinePlatform()) ~ "\n  ],\n  \"architecture\": [\n    " ~ stringArray(determineArchitecture()) ~ "\n   ],\n}\n__dub_probe_end__");
string[] determinePlatform()
{
	string[] ret = null;
	ret ~= "linux";
	ret ~= "posix";
	return ret;
}
string[] determineArchitecture()
{
	string[] ret = null;
	ret ~= "x86_64";
	return ret;
}
string determineCompiler()
{
	return "ldc";
}
toString!2100
{
	enum string toString = "2100";

}

v1.31 AST:

module dub_platform_probe;
import object;
enum toString(int v) = v.stringof;
string stringArray(string[] ary)
{
	string res = null;
	{
		scope string[] __r3 = ary[];
		ulong __key2 = 0LU;
		for (; __key2 < __r3.length; __key2 += 1LU)
		{
			string e = __r3[__key2];
			ulong i = __key2;
			if (i)
				_d_arrayappendT(res, ", ");
			_d_arrayappendT(res, '"' ~ e ~ '"');
		}
	}
	return res;
}
pragma (msg, "__dub_probe_begin__\n{\n  \"compiler\": \"" ~ determineCompiler() ~ "\",\n  \"frontendVersion\": 2101,\n  \"compilerVendor\": \"LDC\",\n  \"platform\": [\n    " ~ stringArray(determinePlatform()) ~ "\n  ],\n  \"architecture\": [\n    " ~ stringArray(determineArchitecture()) ~ "\n   ],\n}\n__dub_probe_end__");
string[] determinePlatform()
{
	string[] ret = null;
	(string __appendtmp7 = "linux";) , (_d_arrayappendcTX(ret, 1LU) , ret[ret.length - 1LU] = __appendtmp7 , ret);
	(string __appendtmp8 = "posix";) , (_d_arrayappendcTX(ret, 1LU) , ret[ret.length - 1LU] = __appendtmp8 , ret);
	return ret;
}
string[] determineArchitecture()
{
	string[] ret = null;
	(string __appendtmp9 = "x86_64";) , (_d_arrayappendcTX(ret, 1LU) , ret[ret.length - 1LU] = __appendtmp9 , ret);
	return ret;
}
string determineCompiler()
{
	return "ldc";
}
toString!2101
{
	enum string toString = "2101";

}
_d_arrayappendT!(string, immutable(char))
{
	pure nothrow ref @trusted string _d_arrayappendT(return ref scope string x, scope string y)
	{
		import core.stdc.string : memcpy;
		import core.internal.traits : hasElaborateCopyConstructor, Unqual;
		import core.lifetime : copyEmplace;
		enum bool hasPostblit = false;
		ulong length = x.length;
		_d_arrayappendcTX(x, y.length);
		if (y.length)
		{
			char* xptr = cast(char*)&x[length];
			immutable immutable(ulong) size = 1LU;
			memcpy(cast(void*)xptr, cast(const(void*))cast(char*)&y[0], y.length * 1LU);
		}
		return x;
	}

}
_d_arrayappendcTXImpl!(string, immutable(char))
{
	import core.internal.array.utils : _d_HookTraceImpl;
	private enum string errorMessage = "Cannot append to array if compiling without support for runtime type information!";
	pure nothrow ref @trusted string _d_arrayappendcTX(return ref scope string px, ulong n)
	{
		TypeInfo_Array ti = typeid(string);
		byte[] pxx = (cast(byte*)cast(immutable(char)*)px)[0..px.length];
		_d_arrayappendcTX(ti, pxx, n);
		px = (cast(immutable(char)*)cast(byte*)pxx)[0..pxx.length];
		return px;
	}
	alias _d_arrayappendcTXTrace = auto pure nothrow @trusted string _d_HookTraceImpl(string file, int line, string funcname, return ref scope string _param_3, ulong _param_4)
	{
		import core.internal.array.utils : gcStatsPure, accumulatePure;
		string name = "string";
		ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;
		try
		{
			return _d_arrayappendcTX(_param_3, _param_4);
		}
		finally
		{
			ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;
			if (size > 0LU)
				if (!accumulatePure(file, line, funcname, name, size))
				{
					assert(0);
				}
		}
	}
	;
}
_d_HookTraceImpl!(string, _d_arrayappendcTX, "Cannot append to array if compiling without support for runtime type information!")
{
	auto pure nothrow @trusted string _d_HookTraceImpl(string file, int line, string funcname, return ref scope string _param_3, ulong _param_4)
	{
		import core.internal.array.utils : gcStatsPure, accumulatePure;
		string name = "string";
		ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;
		try
		{
			return _d_arrayappendcTX(_param_3, _param_4);
		}
		finally
		{
			ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;
			if (size > 0LU)
				if (!accumulatePure(file, line, funcname, name, size))
				{
					assert(0);
				}
		}
	}

}
Parameters!(_d_arrayappendcTX)
{
	alias Parameters = (return ref scope string, ulong);

}
FunctionTypeOf!(_d_arrayappendcTX)
{
	alias pure nothrow ref @trusted string FunctionTypeOf(return ref scope string px, ulong n);

}
hasElaborateCopyConstructor!(immutable(char))
{
	enum bool hasElaborateCopyConstructor = false;

}
Unqual!(immutable(char), char)
{
	alias Unqual = char;

}
TraceHook!("string", "_d_arrayappendcTX")
{
	const const(char[]) TraceHook = "\n        import core.internal.array.utils : gcStatsPure, accumulatePure;\n\n        pragma(inline, false);\n        string name = `string`;\n\n        // FIXME: use rt.tracegc.accumulator when it is accessable in the future.\n        version (tracegc)\n    {\n\n            import core.stdc.stdio;\n\n            printf(\"%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\\n\",\n            \"_d_arrayappendcTX\".ptr,\n                file.length, file.ptr,\n                line,\n                funcname.length, funcname.ptr,\n                name.length, name.ptr\n            );\n        }\n\n        ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;\n\n        scope(exit)\n        {\n            ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;\n            if (size > 0)\n                if (!accumulatePure(file, line, funcname, name, size)) {\n                    // This 'if' and 'assert' is needed to force the compiler to not remove the call to\n                    // `accumulatePure`. It really want to do that while optimizing as the function is\n                    // `pure` and it does not influence the result of this hook.\n\n                    // `accumulatePure` returns the value of `size`, which can never be zero due to the\n                    // previous 'if'. So this assert will never be triggered.\n                    assert(0);\n                }\n        }\n    ";

}
_d_arrayappendcTXImpl!(string[], string)
{
	import core.internal.array.utils : _d_HookTraceImpl;
	private enum string errorMessage = "Cannot append to array if compiling without support for runtime type information!";
	pure nothrow ref @trusted string[] _d_arrayappendcTX(return ref scope string[] px, ulong n)
	{
		TypeInfo_Array ti = typeid(string[]);
		byte[] pxx = (cast(byte*)cast(string*)px)[0..px.length];
		_d_arrayappendcTX(ti, pxx, n);
		px = (cast(string*)cast(byte*)pxx)[0..pxx.length];
		return px;
	}
	alias _d_arrayappendcTXTrace = auto pure nothrow @trusted string[] _d_HookTraceImpl(string file, int line, string funcname, return ref scope string[] _param_3, ulong _param_4)
	{
		import core.internal.array.utils : gcStatsPure, accumulatePure;
		string name = "string[]";
		ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;
		try
		{
			return _d_arrayappendcTX(_param_3, _param_4);
		}
		finally
		{
			ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;
			if (size > 0LU)
				if (!accumulatePure(file, line, funcname, name, size))
				{
					assert(0);
				}
		}
	}
	;
}
_d_HookTraceImpl!(string[], _d_arrayappendcTX, "Cannot append to array if compiling without support for runtime type information!")
{
	auto pure nothrow @trusted string[] _d_HookTraceImpl(string file, int line, string funcname, return ref scope string[] _param_3, ulong _param_4)
	{
		import core.internal.array.utils : gcStatsPure, accumulatePure;
		string name = "string[]";
		ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;
		try
		{
			return _d_arrayappendcTX(_param_3, _param_4);
		}
		finally
		{
			ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;
			if (size > 0LU)
				if (!accumulatePure(file, line, funcname, name, size))
				{
					assert(0);
				}
		}
	}

}
Parameters!(_d_arrayappendcTX)
{
	alias Parameters = (return ref scope string[], ulong);

}
FunctionTypeOf!(_d_arrayappendcTX)
{
	alias pure nothrow ref @trusted string[] FunctionTypeOf(return ref scope string[] px, ulong n);

}
TraceHook!("string[]", "_d_arrayappendcTX")
{
	const const(char[]) TraceHook = "\n        import core.internal.array.utils : gcStatsPure, accumulatePure;\n\n        pragma(inline, false);\n        string name = `string[]`;\n\n        // FIXME: use rt.tracegc.accumulator when it is accessable in the future.\n        version (tracegc)\n    {\n\n            import core.stdc.stdio;\n\n            printf(\"%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\\n\",\n            \"_d_arrayappendcTX\".ptr,\n                file.length, file.ptr,\n                line,\n                funcname.length, funcname.ptr,\n                name.length, name.ptr\n            );\n        }\n\n        ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;\n\n        scope(exit)\n        {\n            ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;\n            if (size > 0)\n                if (!accumulatePure(file, line, funcname, name, size)) {\n                    // This 'if' and 'assert' is needed to force the compiler to not remove the call to\n                    // `accumulatePure`. It really want to do that while optimizing as the function is\n                    // `pure` and it does not influence the result of this hook.\n\n                    // `accumulatePure` returns the value of `size`, which can never be zero due to the\n                    // previous 'if'. So this assert will never be triggered.\n                    assert(0);\n                }\n        }\n    ";

}

@Geod24
Copy link
Contributor

Geod24 commented Feb 24, 2023

I never considered Wasm / other target with this. We should probably expose a way in dub to disable it / hardcode it.

@ryuukk
Copy link
Contributor Author

ryuukk commented Feb 24, 2023

dub shouldn't compile anything other than my project, this feature should be gone, if you need query information about compilers, send PR to dmd/ldc to provide cli option to return information you need

@kinke
Copy link
Member

kinke commented Feb 24, 2023

I don't think that'd be easy, and the problem is much bigger than just dub's probe file - any string-concat for CTFE etc. doesn't work anymore in general for such targets with incomplete C bindings in druntime. If the problem here at least is only the memcpy import, then we have an ldc.intrinsics.llvm_memcpy alternative for LDC.

kinke added a commit to kinke/dmd that referenced this issue Feb 25, 2023
This is important for CTFE-string-appending etc. for targets without
proper druntime support, such as WebAssembly.

See ldc-developers/ldc#4324 for an examplary
breakage caused by the hook addition in D v2.101, rendering dub
totally unusable for such targets.

In particular, skip all the `-profile=gc` stuff when not using that
cmdline option.
@kinke
Copy link
Member

kinke commented Feb 25, 2023

I've tested this - not with master, but with #4323. memcpy wasn't the problem, but all the -profile=gc extra stuff (not supported by LDC anyway) was. Applying my DMD PR linked above got the dub probe file to compile for wasm32.

Edit: v1.32 AST with those changes:

module dub_platform_probe;
import object;
enum toString(int v) = v.stringof;
string stringArray(string[] ary)
{
	string res = null;
	{
		scope string[] __r3 = ary[];
		uint __key2 = 0u;
		for (; __key2 < __r3.length; __key2 += 1u)
		{
			string e = __r3[__key2];
			uint i = __key2;
			if (i)
				_d_arrayappendT(res, ", ");
			_d_arrayappendT(res, '"' ~ e ~ '"');
		}
	}
	return res;
}
pragma (msg, "__dub_probe_begin__\n{\n  \"compiler\": \"" ~ determineCompiler() ~ "\",\n  \"frontendVersion\": 2102,\n  \"compilerVendor\": \"LDC\",\n  \"platform\": [\n    " ~ stringArray(determinePlatform()) ~ "\n  ],\n  \"architecture\": [\n    " ~ stringArray(determineArchitecture()) ~ "\n   ],\n}\n__dub_probe_end__");
string[] determinePlatform()
{
	string[] ret = null;
	(string __appendtmp5 = "wasm";) , (_d_arrayappendcTX(ret, 1u) , ret[ret.length - 1u] = __appendtmp5 , ret);
	return ret;
}
string[] determineArchitecture()
{
	string[] ret = null;
	return ret;
}
string determineCompiler()
{
	return "ldc";
}
toString!2102
{
	enum string toString = "2102";

}
_d_arrayappendT!(string, immutable(char))
{
	pure nothrow ref @trusted string _d_arrayappendT(return ref scope string x, scope string y)
	{
		import core.stdc.string : memcpy;
		import core.internal.traits : hasElaborateCopyConstructor, Unqual;
		enum bool hasPostblit = false;
		uint length = x.length;
		_d_arrayappendcTX(x, y.length);
		if (y.length)
		{
			char* xptr = cast(char*)&x[length];
			immutable immutable(uint) size = 1u;
			memcpy(cast(void*)xptr, cast(const(void*))cast(char*)&y[0], y.length * 1u);
		}
		return x;
	}

}
_d_arrayappendcTXImpl!(string, immutable(char))
{
	import core.internal.array.utils : _d_HookTraceImpl;
	private enum string errorMessage = "Cannot append to array if compiling without support for runtime type information!";
	pure nothrow ref @trusted string _d_arrayappendcTX(return ref scope string px, uint n)
	{
		TypeInfo_Array ti = typeid(string);
		byte[] pxx = (cast(byte*)cast(immutable(char)*)px)[0..px.length];
		_d_arrayappendcTX(ti, pxx, n);
		px = (cast(immutable(char)*)cast(byte*)pxx)[0..pxx.length];
		return px;
	}
	version (D_ProfileGC)
	{
		alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage)
		{
		}
		;
	}
}
hasElaborateCopyConstructor!(immutable(char))
{
	enum bool hasElaborateCopyConstructor = false;

}
Unqual!(immutable(char), char)
{
	alias Unqual = char;

}
_d_arrayappendcTXImpl!(string[], string)
{
	import core.internal.array.utils : _d_HookTraceImpl;
	private enum string errorMessage = "Cannot append to array if compiling without support for runtime type information!";
	pure nothrow ref @trusted string[] _d_arrayappendcTX(return ref scope string[] px, uint n)
	{
		TypeInfo_Array ti = typeid(string[]);
		byte[] pxx = (cast(byte*)cast(string*)px)[0..px.length];
		_d_arrayappendcTX(ti, pxx, n);
		px = (cast(string*)cast(byte*)pxx)[0..pxx.length];
		return px;
	}
	version (D_ProfileGC)
	{
		alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage)
		{
		}
		;
	}
}

dlang-bot pushed a commit to dlang/dmd that referenced this issue Feb 25, 2023
This is important for CTFE-string-appending etc. for targets without
proper druntime support, such as WebAssembly.

See ldc-developers/ldc#4324 for an examplary
breakage caused by the hook addition in D v2.101, rendering dub
totally unusable for such targets.

In particular, skip all the `-profile=gc` stuff when not using that
cmdline option.
@ryuukk
Copy link
Contributor Author

ryuukk commented Feb 25, 2023

thanks!

kinke added a commit that referenced this issue Feb 25, 2023
This is important for CTFE-string-appending etc. for targets without
proper druntime support, such as WebAssembly.

See #4324 for an examplary
breakage caused by the hook addition in D v2.101, rendering dub
totally unusable for such targets.

In particular, skip all the `-profile=gc` stuff when not using that
cmdline option.
@JohanEngelen JohanEngelen added the B-webassembly WASM-related label Mar 3, 2023
@kinke
Copy link
Member

kinke commented May 14, 2023

This was fixed in druntime v2.102 (=> LDC v1.32).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-webassembly WASM-related
Projects
None yet
Development

No branches or pull requests

4 participants