Skip to content

builtin: fix mix prod and debug ucrt lib #24498

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

Merged
merged 2 commits into from
May 21, 2025

Conversation

kbkpbot
Copy link
Contributor

@kbkpbot kbkpbot commented May 16, 2025

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

Copy link

Connected to Huly®: V_0.6-22866

@kbkpbot
Copy link
Contributor Author

kbkpbot commented May 16, 2025

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
Contributor

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

@spytheman
Copy link
Member

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

@Ekopalypse
Copy link
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
Copy link
Contributor Author

kbkpbot commented May 18, 2025

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
Contributor

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

@Ekopalypse
Copy link
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
Member

Why 4 instead of 2?

@spytheman
Copy link
Member

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
Contributor

Why 4 instead of 2?

Because ucrt and msvcrt are not 100% compatible.

@Ekopalypse
Copy link
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
74 checks passed
@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