Skip to content

builtin: fix mix prod and debug ucrt lib - #24498

Merged
spytheman merged 2 commits into
vlang:masterfrom
kbkpbot:builtin-fix-mix-debug-prod
May 21, 2025
Merged

spytheman merged 2 commits into
vlang:masterfrom
kbkpbot:builtin-fix-mix-debug-prod

Conversation

@kbkpbot

@kbkpbot kbkpbot commented May 16, 2025 •

Copy link
Copy Markdown
Contributor

This PR fix a Windows/msvc issue

v -prod vlib\v\gen\c\testdata\self_printer_with_prod.vv

When execute the generated .exe, it output nothing.

This is due to a mix using of debug/non-debug of ucrt.lib/ucrtd.lib. It will cause os.c.v fdopen crash.

It may also related to issue #20923

@huly-for-github

Copy link
Copy Markdown

Connected to Huly®: V_0.6-22866

@kbkpbot

kbkpbot commented May 16, 2025

Copy link
Copy Markdown
Contributor Author

Or can we remove the lines?

$if windows && msvc {
	$if prod {
		#flag ucrt.lib
	} $else {
		#flag ucrtd.lib
	}
}

As when compile with /MD, cl will link with ucrt.lib; when compile with /MDd, cl will link with ucrtd.lib automatically.

@JalonSolov

Copy link
Copy Markdown
Collaborator

If we're sure /MD//MDd will be passed along properly, then I agree those lines could be removed.

@spytheman

Copy link
Copy Markdown
Contributor

@Ekopalypse can you please check, if that works for you?

@Ekopalypse

Copy link
Copy Markdown
Contributor

@spytheman

Thanks for the ping about the planned change,
unfortunately we were instructed to switch to Rust,
so "unfortunately" it doesn't affect me anymore.

I don't see any problems for my private projects either,
as the projects that use GCBoehm are linked with their own compiled version.

Everything that comes now assumes that what was actually meant was v -prod -cc msvc -gc boehm ...,
since I have no problems with the test when it is compiled without GC,
neither in release mode (-prod) nor in standard mode (without -prod).

D:\ProgramData\Compiler\v>v wipe-cache
V cache folder C:\Users\user\.vmodules\.cache was wiped.
V tmp.c and tests folder folder C:\Users\user\AppData\Local\Temp\v_0 was wiped.

D:\ProgramData\Compiler\v>ls -ltr vlib\v\gen\c\testdata\self_printer_with_prod.*
294 B Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.vv'
294 B Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.out'

D:\ProgramData\Compiler\v>v -cc msvc vlib\v\gen\c\testdata\self_printer_with_prod.vv

D:\ProgramData\Compiler\v>ls -ltr vlib\v\gen\c\testdata\self_printer_with_prod.*
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.vv'
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.out'
213 KB Sat May 17 17:36:48 2025  'vlib\v\gen\c\testdata\self_printer_with_prod.exe'

D:\ProgramData\Compiler\v>vlib\v\gen\c\testdata\self_printer_with_prod.exe
// vtest vflags: -prod -skip-unused
// See https://github.com/vlang/v/issues/20923
module main

import os
import io

fn main() {
        mut file := os.open_file(@FILE, 'r')!
        mut buff_reader := io.new_buffered_reader(reader: file)
        for {
                a := buff_reader.read_line() or { break }
                println(a)
        }
}

D:\ProgramData\Compiler\v>v -prod -cc msvc vlib\v\gen\c\testdata\self_printer_with_prod.vv

D:\ProgramData\Compiler\v>ls -ltr vlib\v\gen\c\testdata\self_printer_with_prod.*
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.vv'
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.out'
 80 KB Sat May 17 17:37:11 2025  'vlib\v\gen\c\testdata\self_printer_with_prod.exe'

D:\ProgramData\Compiler\v>vlib\v\gen\c\testdata\self_printer_with_prod.exe
// vtest vflags: -prod -skip-unused
// See https://github.com/vlang/v/issues/20923
module main

import os
import io

fn main() {
        mut file := os.open_file(@FILE, 'r')!
        mut buff_reader := io.new_buffered_reader(reader: file)
        for {
                a := buff_reader.read_line() or { break }
                println(a)
        }
}

Yes, a change seems to be necessary, as the ucrt is currently also linked against a debug version in release mode.
The test fails in both release and standard mode.

D:\ProgramData\Compiler\v>v -prod -cc msvc -gc boehm vlib\v\gen\c\testdata\self_printer_with_prod.vv

D:\ProgramData\Compiler\v>ls -ltr vlib\v\gen\c\testdata\self_printer_with_prod.*
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.vv'
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.out'
208 KB Sat May 17 17:37:40 2025  'vlib\v\gen\c\testdata\self_printer_with_prod.exe'

D:\ProgramData\Compiler\v>vlib\v\gen\c\testdata\self_printer_with_prod.exe

D:\ProgramData\Compiler\v>
D:\ProgramData\Compiler\v>v -cc msvc -gc boehm vlib\v\gen\c\testdata\self_printer_with_prod.vv

D:\ProgramData\Compiler\v>ls -ltr vlib\v\gen\c\testdata\self_printer_with_prod.*
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.vv'
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.out'
378 KB Sat May 17 17:38:03 2025  'vlib\v\gen\c\testdata\self_printer_with_prod.exe'

D:\ProgramData\Compiler\v>vlib\v\gen\c\testdata\self_printer_with_prod.exe

D:\ProgramData\Compiler\v>

When using symbols v -g -prod -cc msvc -gc boehm ... everything seems to work.

D:\ProgramData\Compiler\v>v -g -prod -cc msvc vlib\v\gen\c\testdata\self_printer_with_prod.vv

D:\ProgramData\Compiler\v>ls -ltr vlib\v\gen\c\testdata\self_printer_with_prod.*
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.vv'
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.out'
 84 KB Sat May 17 17:38:37 2025  'vlib\v\gen\c\testdata\self_printer_with_prod.exe'
684 KB Sat May 17 17:38:37 2025 󰪪 'vlib\v\gen\c\testdata\self_printer_with_prod.pdb'

D:\ProgramData\Compiler\v>vlib\v\gen\c\testdata\self_printer_with_prod.exe
// vtest vflags: -prod -skip-unused
// See https://github.com/vlang/v/issues/20923
module main

import os
import io

fn main() {
        mut file := os.open_file(@FILE, 'r')!
        mut buff_reader := io.new_buffered_reader(reader: file)
        for {
                a := buff_reader.read_line() or { break }
                println(a)
        }
}

D:\ProgramData\Compiler\v>v -g -cc msvc vlib\v\gen\c\testdata\self_printer_with_prod.vv

D:\ProgramData\Compiler\v>ls -ltr vlib\v\gen\c\testdata\self_printer_with_prod.*
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.vv'
294 B  Tue Apr 23 07:57:31 2024  'vlib\v\gen\c\testdata\self_printer_with_prod.out'
237 KB Sat May 17 17:39:03 2025  'vlib\v\gen\c\testdata\self_printer_with_prod.exe'
940 KB Sat May 17 17:39:03 2025 󰪪 'vlib\v\gen\c\testdata\self_printer_with_prod.pdb'
722 KB Sat May 17 17:39:03 2025  'vlib\v\gen\c\testdata\self_printer_with_prod.ilk'

D:\ProgramData\Compiler\v>vlib\v\gen\c\testdata\self_printer_with_prod.exe
// vtest vflags: -prod -skip-unused
// See https://github.com/vlang/v/issues/20923
module main

import os
import io

fn main() {
        mut file := os.open_file(@FILE, 'r')!
        mut buff_reader := io.new_buffered_reader(reader: file)
        for {
                a := buff_reader.read_line() or { break }
                println(a)
        }
}

D:\ProgramData\Compiler\v>

However, I see another issue with the GC, the supplied gc.obj is actually linked against MSVCRTD.
And that, I assume, is the actual cause.

D:\ProgramData\Compiler\v>dumpbin /DIRECTIVES thirdparty\libgc\gc.obj
Microsoft (R) COFF/PE Dumper Version 14.43.34810.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file thirdparty\libgc\gc.obj

File Type: COFF OBJECT

   Linker Directives
   -----------------
   /DEFAULTLIB:uuid.lib
   /DEFAULTLIB:uuid.lib
   /DEFAULTLIB:MSVCRTD
   /DEFAULTLIB:OLDNAMES

@kbkpbot

kbkpbot commented May 18, 2025 •

Copy link
Copy Markdown
Contributor Author

This bug also report in issue #24229

So, do we need two version of gc.obj ? one for debug, anther for release?
for example, gc_r.obj, gc_d.obj?

@JalonSolov

Copy link
Copy Markdown
Collaborator

With the way the Windows stuff works... I'd say yes.

@Ekopalypse

Copy link
Copy Markdown
Contributor

I think you need 4 versions. Two for msvcrt and two for ucrt.
Which also means that you have to find out which toolset is currently installed and which runtime you want to link to.
If you no longer want to support msvcrt this also means that older operating systems, afaik anything < Windows 10 are no longer supported.
Another option would be to create GC locally for each build. Advantage, the toolset does the work, disadvantage the build takes a bit longer.
The best option would be for GC to be part of VLang.

@spytheman

Copy link
Copy Markdown
Contributor

Why 4 instead of 2?

@spytheman

Copy link
Copy Markdown
Contributor

Another option would be to create GC locally for each build. Advantage, the toolset does the work, disadvantage the build takes a bit longer.

That is an option that is worth exploring, since the .o file can be compiled once and then reused, amortizing the initial slowdown. I will try it.

@Ekopalypse

Copy link
Copy Markdown
Contributor

Why 4 instead of 2?

Because ucrt and msvcrt are not 100% compatible.

@Ekopalypse

Copy link
Copy Markdown
Contributor

That is an option that is worth exploring, since the .o file can be compiled once and then reused, amortizing the initial slowdown. I will try it.

Just to avoid confusion, what I mean here is that it is to be built for any project and NOT just the v build.
It could be that the current project wants to use ucrt and another one wants to use msvcrt.

@spytheman
spytheman merged commit 89305aa into vlang:master May 21, 2025
@kbkpbot
kbkpbot deleted the builtin-fix-mix-debug-prod branch May 21, 2025 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants