[HN Gopher] Some sanity for C and C++ development on Windows
       ___________________________________________________________________
        
       Some sanity for C and C++ development on Windows
        
       Author : ingve
       Score  : 99 points
       Date   : 2021-12-31 11:47 UTC (11 hours ago)
        
 (HTM) web link (nullprogram.com)
 (TXT) w3m dump (nullprogram.com)
        
       | gigel82 wrote:
       | You can set UTF-8 system-wide for 3+ years; I've been doing it on
       | all my boxes and never had issues. I suspect in a few years this
       | will just be the default:
       | https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows#U...
        
       | layer8 wrote:
       | Can anyone elucidate whether the new UTF-8 codepage allows
       | working with filenames that aren't valid UTF-16 (i.e. containing
       | mismatched surrogate code points)?
       | 
       | In general I think it's best to stick with the native "W"
       | functions and/or wchar_t on Windows.
        
         | ChrisSD wrote:
         | It does not. Invalid UTF-16 (aka unpaired surrogates) are
         | replaced by the Unicode REPLACEMENT_CHARACTER () However, in
         | practice such filenames are only produced by malicious software
         | and many large products won't work with them anyway (e.g.
         | Microsoft's own VSCode).
        
       | asveikau wrote:
       | I've done a lot of Win32 development in C and C++.
       | 
       | People here are saying don't expect it to be Unix, and that's
       | fine. When I write for Windows, everything is PWSTR and that's
       | fine.
       | 
       | But I have seen a lot of people get tripped up on this. People
       | who are not well versed in the issue have no idea that using
       | fopen() or CreateFileA() will make their program unable to access
       | the full range of possible filenames, varying with the language
       | setting. I've absolutely seen bugs arise with this in the 21st
       | century.
       | 
       | The old "ACP" is meant for compatibility with pre-unicode
       | software, but that hasn't been a big concern for something like
       | 20 years. It is a much bigger issue that people are unaware of
       | this history and expect char* functions to just work.
        
         | lazyjeff wrote:
         | I have done a lot of Win32 as well, and recently started a new
         | project after a long haitus. The problem is there are some very
         | occasional things that use char*, and so you have to keep that
         | in mind: for example, some parameters in wWinMain, many cross-
         | platform libraries that I want to link to, or some of the C++
         | library functions mentioned in that article. Converting between
         | char* and wchar_t requires being a bit careful not to cause a
         | buffer overflow. It's a lot of mental overhead to deal with it
         | all, but you're right that if you're mainly just calling Win32,
         | then sticking with the wide version of functions and strings
         | will mostly be fine. Microsoft could certainly make this easier
         | by offering a "wWin32" project that only has the wide version
         | of libraries and documentation to prevent mistakes.
        
           | q-big wrote:
           | > Microsoft could certainly make this easier by offering a
           | "wWin32" project that only has the wide version of libraries
           | 
           | Using API functions ending with ...A (for the ANSI version)
           | like CreateFileA is actually rather lowlevel style and means
           | that you know what you do (the same holds for the ...W
           | versions) and explicitly want it this way.
           | 
           | Normally, you use CreateFile and Visual C++ by default sets
           | the proper preprocessor symbols such that CreateFileW will be
           | used. If you pass a char*, you will get compile errors.
           | 
           | In other words: the infrastructure is there to avoid this
           | kind of errors - and it is even used by default. But if you
           | make it explicit in your code that the ANSI version of an API
           | function (CreateFileA) should be used instead of using
           | CreateFile, don't complain that the compiler does obey and
           | this turns out to be a bad idea.
        
             | int_19h wrote:
             | This used to be the case, but not anymore, I think. If you
             | look at MSDN docs these days, they explicitly document ...A
             | and ...W functions separately. If you create a new Win32
             | project in Visual Studio, it's halfway through - sometimes
             | it will call the ...W functions explicitly, other times it
             | will use the macros. But overall it feels like the intent
             | is to push devs towards explicitness.
             | 
             | The macros in question were always a bad idea, because they
             | applied to all identifiers. So e.g. if you had a method
             | named CreateFile in your class somewhere, and somebody did
             | #include <windows.h> along with the header defining that
             | class, you'd get a linker error.
        
       | bullen wrote:
       | The only flaw Windows has is that you are not allowed to
       | redistribute the cl.exe compiler. For my game engine it's a 35MB
       | zip!
       | 
       | https://developercommunity.visualstudio.com/t/allow-redistri...
        
         | jcelerier wrote:
         | I'm doing it with clang. As a bonus I get better performance
         | than I did with msvc.
        
           | bullen wrote:
           | I tried looking at all other compilers, the only that fit my
           | size constraints was tcc... that would mean dropping
           | std::string and only use ASCII char*... not a big deal for my
           | game because my .ttf fonts dont have anything else but for
           | other projects throwing UTF-8 out of the window might be a
           | show stopper!?
           | 
           | Also considered Rust, but that is so bloated/slow! Can't stop
           | anyone from using Rust for the game in the future though,
           | because any .so/.dll will be able to hot-deploy.
        
             | dundarious wrote:
             | std::string is basically just the following:
             | struct std_string {           union {             char
             | small[16];             struct { size_t len; char* buf; }
             | big;           } value;           unsigned char is_big;
             | };
             | 
             | There is nothing it does regarding support for non-ASCII
             | characters over what you get from buf and len. And for
             | UTF-8, you don't even need len, plain old strlen from the
             | 1980s works fine on valid UTF-8, so plain char* from C
             | works just as well.
             | 
             | And the union is just a performance optimization for small
             | strings (is_big is probably not an additional field in good
             | impls, but I separated it here), it's logically identical
             | to just the buf and len.
             | 
             | Which is all just to say, go for it with tcc!
        
             | jcelerier wrote:
             | I don't understand, shipping 50mb of cl.exe is fine but
             | shipping clang isn't ?
        
       | kazinator wrote:
       | > _I'm excluding Cygwin and its major fork, MSYS2, despite not
       | inheriting any of these flaws. They change so much that they're
       | effectively whole new platforms, not truly "native" to Windows._
       | 
       | Ah, but Cygwin doesn't actually change so much that we can't
       | scale some of it back, to have sane C and C++ development on
       | Windows.
       | 
       | https://www.kylheku.com/cygnal/
       | 
       | Build a Cygwin program, then do a switcheroo on the cygwin1.dll
       | to deploy as a Windows program.
       | 
       | I developed Cygnal to have an easy and sane way of porting the
       | TXR language to Windows.
       | 
       | You can control the Windows console with <termios.h> and
       | ANSI/VT100 escapes. Literally not a line of code has to change
       | from Linux!
       | 
       | In Cygnal, I scaled back various POSIXy things in Cygwin. For
       | instance:
       | 
       | - normal paths with drive letter names work.
       | 
       | - the chdir() function understands the DOS/Windows concept of a
       | logged drive: that chdir("D:") will change to the current
       | directory remembered for the D drive.
       | 
       | - drive relative paths like "d:doc.txt" work (using the working
       | directory associated with the D drive).
       | 
       | - PATH is semicolon separated, not colon.
       | 
       | - The HOME variable isn't /home/username, but is rewritten from
       | the value of USERPROFILE. (I had problems with native Windows Vim
       | launched from a Cygwin program, and then looking for a
       | nonexistent /home due to the frobbed variable, so I was sure to
       | address this issue).
       | 
       | - popen and system do not look for /bin/sh. They use cmd.exe!
       | 
       | - when exec detects that "/bin/sh" "-c" "<arg>" is being spawned,
       | it rewrites this to cmd.exe. The benefit is that interpreter
       | programs which expose command invocation functions which they
       | implement from scratch by forking and execing /bin/sh -c command
       | are thereby retargetted to windows.
       | 
       | - the /cygdrive directory is gone
       | 
       | - /dev is available as dev:/ so you can access devices.
        
       | pjmlp wrote:
       | Sanity only required for those that fight against the platform
       | and insist in carrying their UNIX habits to every platform they
       | touch.
       | 
       | Embrace C++ Builder, Visual C++ or Qt.
       | 
       | No sanity medicine required.
        
       | feldrim wrote:
       | > On Windows, C and C++ is so poorly hooked up to operating
       | system interfaces that most portable or mostly-portable software
       | -- programs which work perfectly elsewhere -- are subtly broken
       | on Windows.
       | 
       | I believe that the problem is about the definition of
       | "elsewhere". The elsewhere is called POSIX. The portability is
       | based on POSIX. So the article can be summed as "Windows is not
       | POSIX compliant".
        
         | pjc50 wrote:
         | They did build a POSIX interface, mostly so they could mislead
         | the DOD into buying NT to meet POSIX needs.
         | https://en.wikipedia.org/wiki/Microsoft_POSIX_subsystem
        
           | feldrim wrote:
           | Yes. It did. It's just another subsystem over the kernel.
           | Kernel did not care about POSIX. The POSIX subsystem is yet
           | another abstraction layer, not too different from CygWin on
           | MinGW for the use case. Since it was limited, it would not
           | solve the portability problem that the author mentioned.
        
             | hyperman1 wrote:
             | It also means mixing windows and posix code was impossible.
             | If you chose posix, you were locked in an extremely limited
             | text-only world with no good path to any extras windows
             | could offer.
             | 
             | This architecture made it possible to claim posix
             | compatibility on paper, while making it clear microsoft
             | would make your life hell if you tried to actually use it
        
           | phendrenad2 wrote:
           | They didn't mislead. I don't think the DOD mandated full
           | POSIX compliance, and they really only wanted POSIX-style
           | fine-grained ACLs.
        
         | [deleted]
        
         | feldrim wrote:
         | > The UTF-8 encoding was invented in 1992 and standardized by
         | January 1993. UTF-8 was adopted by the unix world over the
         | following years due to its backwards-compatibility
         | 
         | I'd like to add some historical background the UTF-8 problem
         | mentioned there. UTF-8 was standardized in 1992. But the first
         | Linux using UTF-8 as the default encoding was RedHat in 2002
         | [1]. 10 years later!
         | 
         | On the other hand, Windows started using Unicode before it was
         | standardized, and back then there was no UTF-8. Or as Raymond
         | Chen put it, "Windows adopted Unicode before the C language
         | did" [2].
         | 
         | [1] https://www.cl.cam.ac.uk/~mgk25/unicode.html#linux
         | 
         | [2]
         | https://devblogs.microsoft.com/oldnewthing/20190830-00/?p=10...
        
           | garaetjjte wrote:
           | *nix got lucky by always treating filenames mostly as bag of
           | bytes (except for / and NUL), which delegated encoding to
           | applications and typical passthrough from argv to fopen
           | worked fine. Arguably WinNT way is more ambitious and
           | reliable, but I think ignoring UTF8 existence until 2019 was
           | huge mistake.
        
           | CountSessine wrote:
           | _But the first Linux using UTF-8 as the default encoding was
           | RedHat in 2002_
           | 
           | And then Microsoft spent the next 20 years
           | explaining/complaining to everyone (and this includes Chen)
           | why they couldn't make UTF-8 a code page because it would
           | mean revalidating all of those -A functions for 4-byte
           | characters when they were originally intended for only
           | 3-bytes?
        
           | flohofwoe wrote:
           | There was a time window of a few months between the invention
           | of UTF-8 and the release of Windows NT with UNICODE support.
           | If the two involved parties would have known of each other
           | (and assuming the Windows devs would have understood what a
           | great deal UTF-8 was), I guess Windows could have used UTF-8
           | right from the start.
        
             | jasode wrote:
             | _> If the two involved parties would have known of each
             | other [...], I guess Windows could have used UTF-8 right
             | from the start._
             | 
             | Probably not. The author of this thread's article has
             | incorrect history about UTF-8 being widely accepted in
             | 1993. At least 4 different systems independently chose
             | UCS2/UCS4 instead of UTF-8 in the early 1990s:
             | 
             | - Microsoft Windows NT 3.1
             | 
             | - Sun Java in 1995
             | 
             | - Netscape Javascript in 1995
             | 
             | - Python 2.x
             | 
             | Why? Because before 1996, the Unicode Consortium initially
             | thought 16-bit 65k characters was "more than enough" based
             | on the CJK unification first recommended by language
             | experts from Asia. The wikipedia page on Unicode revision
             | history shows the explosion of extra CJK chars in Unicode
             | 3.1 which exceeded count of 65k didn't happen until 2001:
             | https://en.wikipedia.org/wiki/Unicode#Versions
             | 
             | The prevailing standard in 1993 was UCS-2 and not UTF-8.
             | Considering that a huge revision of an operating system
             | like Windows is a multi-year effort, they were really
             | looking at what the standard was circa ~1991. So Rob Pike's
             | napkin idea of UTF-8 in 1992 and then the later
             | presentation at USENIX in January 1993 -- is really not
             | relevant for a July 1993 release of Windows NT 3.1. The
             | author writing in Dec 2021 has hindsight bias but
             | MS/Java/Python just went with Unicode 1.x UCS2 which was
             | logical at that time.
        
               | mpyne wrote:
               | Even by 1999, when Qt 2 was released, the new "Unicode-
               | aware" QString class used UTF-16 internally, not UTF-8.
               | This remains the internal Qt encoding even today (see
               | https://wiki.qt.io/QString#Unicode_methods_in_QString),
               | although the support for UTF-8 has improved
               | substantially, to the point that Qt assumes that 8-bit
               | strings not provided an alternate encoding are UTF-8,
               | that 8-bit filenames can be expressed as UTF-8, and so on
               | (see https://doc.qt.io/qt-6/unicode.html).
        
               | my123 wrote:
               | In 1991, the decision was way beyond made: https://betawi
               | ki.net/wiki/Windows_NT_3.1_October_1991_build
        
               | feldrim wrote:
               | There're several mistakes in the history. Just like any
               | article, it is based on the biases of the author.
        
               | ChrisSD wrote:
               | Ken Thompson was the one scribbling on a napkin. Rob was
               | the one telling the story later on.
        
             | jcranmer wrote:
             | The addition of Unicode support to Windows NT was probably
             | done a great deal in advance of its actual release--it's
             | not the sort of thing you can throw in the last minute.
             | 
             | It's also worth noting that dealing with UTF-8 correctly is
             | more than just declaring "the encoding of this set of
             | characters is UTF-8"--it does require you rethink how
             | string APIs are designed to work well. If the alternative
             | is a 16-bit fixed-with character format, UTF-8's variable-
             | width format doesn't necessarily look like a wiser idea.
             | It's not until 1996, when Unicode moves from 16-bits to
             | 25-bits, that UTF-8 actually looks like a good thing.
        
       | geofft wrote:
       | Should new programming languages built around internal use of
       | UTF-8 be opting their binaries into this behavior by default?
       | 
       | (I'm mostly thinking about Rust, which I think has to do some
       | contortions on Windows. Probably also Go, to the extent it uses
       | native APIs; arguably Python too.)
        
         | int_19h wrote:
         | The problem right now is that forcing the codepage to UTF-8
         | only works on Windows 10 build 1903+. So quietly forcing this
         | opt-in may result in situations where everything works fine for
         | the devs, but some of their users see breakage for no clear
         | reason.
         | 
         | Long-term, though? Absolutely.
        
         | ChrisSD wrote:
         | The Rust standard library has contortions in order to support
         | invalid UTF-16. To do this it uses an encoding called
         | "WTF-8"[0], which is an extension to UTF-8.
         | 
         | If the standard library dropped this requirement and only
         | supported valid Unicode then it could simply use normal UTF-8
         | instead of WTF-8.
         | 
         | [0]: https://simonsapin.github.io/wtf-8/
        
       | WalterBright wrote:
       | D was initially designed (around 2000) to be agnostic about UTF8,
       | UTF16, and UTF32. The language has full support for all three.
       | 
       | But it gradually became clear that UTF8 predominates.
       | 
       | D best practice now is to do all processing in UTF8. When
       | encountering UTF16 or UTF32, promptly convert it to UTF8, do the
       | processing, and then convert to UTF16 or UTF32 on output. In
       | practice, the only time this is needed is to interface with
       | Windows.
       | 
       | All the D standard library code that interfaces with Windows
       | converts to/from UTF8 to UTF16.
       | 
       | If I was doing a do-over for D, there wouldn't be core language
       | support for UTF16 or UTF32, only library support.
        
         | ChrisSD wrote:
         | UTF-32 was an interesting choice. Was that done for the sake of
         | completeness or was there a specific use case for it?
        
           | WalterBright wrote:
           | It was done for completeness.
           | 
           | I was accused of being an anglophile at one point for not
           | doing everything in UTF-32 :-)
        
       | gavinray wrote:
       | I want to point out that this article doesn't acknowledge this
       | major change, regarding ANSI/Unicode API variants in Windows:
       | > "Until recently, Windows has emphasized "Unicode" -W variants
       | over -A APIs. However, recent releases have used the ANSI code
       | page and -A APIs as a means to introduce UTF-8 support to apps.
       | If the ANSI code page is configured for UTF-8, -A APIs operate in
       | UTF-8. This model has the benefit of supporting existing code
       | built with -A APIs without any code changes."
       | 
       | https://docs.microsoft.com/en-us/windows/apps/design/globali...
       | 
       | It seems not everyone is aware of this, too
        
         | garaetjjte wrote:
         | >I want to point out that this article doesn't acknowledge this
         | major change
         | 
         | But it does? In "How to mostly fix Unicode support" section.
        
       | pornel wrote:
       | Windows is what annoys me about C's portability story. C prides
       | itself on supporting every platform, including exotic and dead
       | ones, but only hypothetically. The spec is all about the
       | potential. All the portability promises end the moment you try to
       | compile anything. It doesn't work, but that is no longer C's
       | problem. It's simultaneously the most portable language in the
       | world, and one that barely works on the most popular desktop OS.
        
         | ziml77 wrote:
         | I wonder if people would still call C portable if there were
         | more non-POSIX-compliant operating systems
        
           | vbezhenar wrote:
           | Microcontrollers usually are not POSIX-compliant. Android and
           | iOS are not POSIX-complaint.
        
           | flohofwoe wrote:
           | The ANSI/ISO C standard library and the POSIX standard are
           | two different things though that just happen to overlap here
           | and there.
        
             | ziml77 wrote:
             | My point is that a lot of people treat the POSIX standard
             | as if it was the C standard library. It's understandable
             | because of how limited the actual standard library is, but
             | it leads to people having a view that an OS is doing things
             | wrong if it's not following POSIX.
        
               | dundarious wrote:
               | I think the proliferation of POSIX-like OSes is mostly
               | down to OS projects wanting there to be useful software
               | that can run on their OS, so they minimize/eliminate the
               | work of porting. It has led to the phenomenon you
               | describe though -- instead of thinking an OS is just too
               | much work to port to, it might be thought of as being
               | "wrong".
        
           | pjmlp wrote:
           | There are plenty of them, the FOSS culture just tends to
           | ignore them.
        
         | flohofwoe wrote:
         | "C the language" is very portable and useful, "C the standard
         | runtime library" much less so because it's essentially stuck in
         | the 80's. Good for very simple UNIX-style command line tools,
         | but not much else.
         | 
         | But for non-trivial projects that's not much of a problem
         | because it's quite trivial to ignore the C stdlib functions and
         | call directly into OS APIs (via your own or 3rd-party cross-
         | platform libraries).
        
           | jstimpfle wrote:
           | Yup, and to complement, a very important technique is to
           | design platform-specific layers such that they call the
           | (portable) application code - not the other way around. The
           | more typical approach is attempting to find abstractions for
           | I/O and other platform specific facilities that can be
           | implemented by all targeted platforms. The issue with that is
           | that it is very hard to really make use of the platform this
           | way, or even implement all abstractions for all platforms
           | without quirks. If instead the platform layer calls the (un-
           | abstracted) portable application code, there is no code that
           | needs to be pushed through misfitting abstractions.
           | 
           | I learned this approach from Handmade Here / Handmade
           | Community and it's probably the deepest architectural lesson
           | I learned anywhere, while it seems to be not widely known.
           | I'm almost tempted to say that the conventional approach is
           | wrong and misguided. However, an issue with the platform-
           | calls-code approach is that the code usually can only
           | communicate asynchronously with the platform (one of the
           | issues with code-calls-platform is the one-shot synchronous
           | nature of function calls). That might not work always, for
           | example, I wanted RDTSC counters or Copy-Paste functionality,
           | and I still do this by finding a platform abstraction that
           | the code can call into directly.
        
             | dundarious wrote:
             | I know RDTSC was just an example, but I really wouldn't
             | worry about going Platform->App->Platform for features that
             | have no architectural concerns or impact (in this case,
             | some number connected to performance, probably a cycle
             | count, that's monotonically increasing).
             | 
             | I/O would be the major no-no.
        
       | gecko wrote:
       | The title of this article had me do a double-take: C and C++
       | development on Windows is _great_. No sanity is needed.
       | 
       | But that's not what the article is about. What the article is
       | about is that the C runtime shim that ships with Visual Studio
       | defaults to using the ANSI API calls without supporting UTF-8,
       | goes on to identify this as "almost certainly political,
       | originally motivated by vendor lock-in" (which it's transparently
       | not), and then talks how Windows makes it impossible to port Unix
       | programs without doing something special.
       | 
       | I half empathize. I'd empathize _more_ if (as the author notes)
       | you couldn 't just use MinGW for ports, which has the benefit
       | that you can just use GCC the whole way down and not deal with
       | VC++ differences, but I get that, when porting very small console
       | programs from Unix, this can be annoying. But when it comes to
       | VC++, the accusations of incompetence and whatnot are just odd to
       | me. Microsoft _robustly_ caters to backwards compatibility. This
       | is why _the app binaries I wrote for Windows 95 still run on my
       | 2018 laptop_. There are heavy trade-offs with that approach which
       | in general have been endlessly debated, one of which is
       | definitely how encodings work, but they 're _trade-offs_. (Just
       | like how Windows won 't allow you to delete or move open files by
       | default, which on the one hand often necessitates rebooting on
       | upgrades, and on the other hand avoids entire classes of security
       | issues that the Unix approach has.)
       | 
       | But on the proprietary interface discussion that comes up
       | multiple times in this article? Windows supports file system
       | transactions, supports opting in to a file being accessed by
       | multiple processes rather than advisory opt-out, has different
       | ideas on what's a valid filename than *nix, supports multiple
       | data streams per file, has an entirely different permission model
       | based around ACLs, etc., and that's to say nothing of how the
       | Windows Console is a fundamentally different beast than a
       | terminal. Of _course_ those need APIs different from the Unix-
       | centric C runtime, and it 's entirely reasonable that you might
       | need to look at them if you're targeting Windows.
        
         | jcelerier wrote:
         | > The title of this article had me do a double-take: C and C++
         | development on Windows is great. No sanity is needed.
         | 
         | we certainly have a different opinion on what "great" means. It
         | takes less time to rebuild my whole toolchain from scratch on
         | Linux (~15 minutes) than it takes to MSVC to download those
         | friggin debug symbols it seems to require whenever I have to
         | debug something (I sometimes have to wait 30-40 minutes and I'm
         | on friggin 2GB fiber ! and that's seemingly every time I have
         | to do something with that wretched MSVC !)
         | 
         | Thankfully now the clang / lld / libc++ / lldb ... toolchain
         | works pretty well on Windows and allows a lot more sanity but
         | still, it's pretty slow compared to Linux.
        
           | badsectoracula wrote:
           | > It takes less time to rebuild my whole toolchain from
           | scratch on Linux (~15 minutes) than it takes to MSVC to
           | download those friggin debug symbols it seems to require
           | whenever I have to debug something
           | 
           | Fun fact: you can do the same in gdb and some distributions
           | (e.g. openSUSE) have it enabled by default. Though you also
           | get the source code too.
           | 
           | I was messing around with DRM/KMS the other day and had some
           | weird issue with an error code, so i placed a breakpoint
           | right before the call - gdb downloaded libdrm and libgbm
           | source code (as well as some other stuff) and let me trace
           | the call right into their code, which was super useful to
           | figure out what was going on (and find a tiny bug in libgbm,
           | which i patched and reported).
        
           | gavinray wrote:
           | I just use the LLVM toolchain -- on Windows and Linux. You
           | really can't beat clang and lld, the ecosystem and tooling is
           | fantastic.
           | 
           | If something absolutely requires MSVC ABI compatibility, I
           | use "clang-cl".
           | 
           | God bless LLVM developers.
        
           | fsloth wrote:
           | "than it takes to MSVC to download those friggin debug
           | symbols it seems to require whenever I have to debug
           | something"
           | 
           | I think you can just unclick the radio button in debug
           | settings that requires that?
        
           | simplestats wrote:
           | Microsoft is certainly evil and all, but I use MSVC on
           | windows and clang on linux and the Windows tools for my
           | project are much smarter and faster when it comes to
           | compiling. Not counting times when the windows machine
           | decides it has more important priorities to attend to rather
           | than doing what I need.
        
           | liversage wrote:
           | I agree that downloading symbols can be oddly slow but you
           | can just turn it off, or only turn it on for specific
           | modules. It can be helpful to have symbols for library code
           | to troubleshoot bugs but typically you only need your own
           | symbols and they are already on your computer with your
           | binaries.
        
           | SloopJon wrote:
           | > Thankfully now the clang / lld / libc++ / lldb ...
           | toolchain works pretty well on Windows
           | 
           | Off topic, but I wonder if anyone knows whether it's possible
           | to use rustc with lld, instead of link.exe? I tend not to
           | have Visual C++ on my home systems. Is it as simple as the
           | Cargo equivalent of LD=lld-link.exe?
        
             | ChrisSD wrote:
             | You would need libraries. E.g. the C runtime and system
             | import libraries (msvcrt.lib, vcruntime.lib, kernel32.lib,
             | etc).
        
           | TinkersW wrote:
           | Debug symbols are stored locally with MSVC, and booting into
           | debug mode only takes a few seconds longer than non-debug,
           | sounds like you are doing something wrong.
        
           | torginus wrote:
           | My main gripe with writing C++ on Linux is the dependency
           | management. If you need to do stuff that's not covered by the
           | standard library, like interfacing with GTK or X11 you are in
           | a world of pain. You need to probably install a distro-
           | specific package in a distro-specific way to get the
           | headers/symbols, use some build tool to configure those
           | distro-specific include/so locations, and hope to god that
           | the distro maintainers didn't upgrade one of those packages
           | (in a breaking way) between the source commit and the time of
           | build.
           | 
           | If you suffer through this, you have an exe that works on
           | your version of Ubuntu, maybe on other versions of Ubuntu or
           | possibly other Debian-based distros. If you want it to also
           | work on Fedora, it's back to tinkering.
           | 
           | Tbh i think the only sane-ish way of building to dockerize
           | your build env with baked-in versions.
           | 
           | In contrast, you pick and SDK and compiler version for
           | Windows, and as long as you install those versions, things
           | will work.
        
             | CountSessine wrote:
             | Versus no dependency management at all? This reasoning
             | falls apart once you need to use a 3rd party library on
             | Windows. There's no standard way of sharing such a thing so
             | you always wind up packaging the whole thing with your
             | program, and handing the whole mess to your users.
             | 
             | Granted, writing an RPM is a special kind of hell, but at
             | least you don't have to package everything with your
             | program. But actually you can still do that - I've done
             | that plenty of times in embedded. You can always ship your
             | program with its dependant libraries the way you always
             | have to on Windows. In fact it's a lot easier because most
             | 3rd party libraries were originally coded on Linux and
             | build more sanely on Linux. And RPATHs are pretty easy to
             | figure out.
             | 
             | Linux gives you options.
        
               | torginus wrote:
               | Yeah, you're right, but you probably need a lot less
               | stuff that's not in the SDK. My go to solution for
               | including dependencies, is just checking in all the
               | dependency .lib, include files into Git LFS (I think this
               | is a rather common approach from what I've seen on Git).
               | For your typical Linux C/C++ project, unless it's made by
               | best in class C++ devs, building can be a pain, most
               | likely because it depends on very particular lib
               | versions, building a largish project from GitHub for
               | Ubuntu 21.10, where the original dev used 20.04 is
               | usually not possible without source/Makefile tweaks. And
               | I don't particularly love the idea of using root access
               | to install packages to just build some random person's
               | project.
               | 
               | IMHO, C++ dependency management kinda stinks, regardless
               | of platform.
        
               | nicoburns wrote:
               | > IMHO, C++ dependency management kinda stinks,
               | regardless of platform.
               | 
               | Indeed, and the fact that it's platform-specific in the
               | first place certainly doesn't help!
        
               | dgfitz wrote:
               | Writing an rpm isn't difficult... is that a commonly held
               | belief? Maybe I don't know what I don't know, but I've
               | found wrapping my head around deb packaging much harder
               | than rpms.
        
             | ufo wrote:
             | About the distro-specific include locations, I try to use
             | pkg-config where possible instead of directly specifying
             | the directories and include flags.
        
             | MaxBarraclough wrote:
             | The problems you've described are the reason we have tools
             | like CMake, no? CMake's reusable _find_ modules handle the
             | heavy lifting of coping with the annoying differences
             | between Linux distros, and for that matter other OSs.
             | 
             | > you have an exe that works on your version of Ubuntu
             | 
             | This is indeed a downside of the Linux approach, it's the
             | price we pay for the significant flexibility that distros
             | have, and the consequent differences between them. Windows
             | has remarkably good binary compatibility, but it's a huge
             | engineering burden.
             | 
             | > Tbh i think the only sane-ish way of building to
             | dockerize your build env with baked-in versions.
             | 
             | This is an option, but bundling an entire userland for
             | every application has downsides that the various Linux
             | package-management systems aim to avoid: wasted storage,
             | wasted memory, and less robust protection against
             | inadvertently using insecure unpatched dependencies.
        
             | badsectoracula wrote:
             | > If you need to do stuff that's not covered by the
             | standard library, like interfacing with GTK or X11 you are
             | in a world of pain [...] If you suffer through this, you
             | have an exe that works on your version of Ubuntu, maybe on
             | other versions of Ubuntu or possibly other Debian-based
             | distros. If you want it to also work on Fedora, it's back
             | to tinkering.
             | 
             | GTK is known to break their ABI across major versions
             | (GTK1->GTK2, GTK2->GTK3, GTK3->GTK4) but as a C ABI it
             | should be compatible between minor versions and everything
             | can be assumed to have GTK2 and GTK3 available anyway. X11
             | as a protocol has always been backwards compatible and Xlib
             | on Linux pretty much never broke the ABI since the 90s.
             | Here is a screenshot with a toolkit i'm working on now and
             | then running the exact same binary (built with dynamic
             | linking - ie. it uses the system's C and X libraries) in
             | 1997 Red Hat in a VM and 2018 Debian (i took that shot some
             | time ago - btw the brown colors is because the VM runs in
             | 4bit VGA mode and i haven't implemented colormap use - it
             | also looks weird in modern X if you run your server at
             | 30bpp/10bpc mode)[0].
             | 
             | Of course that doesn't mean other libraries wont be broken
             | and what you need to do (at least the easy way to do it) is
             | to build on the oldest version of Linux you plan on
             | supporting so that any references are to those versions
             | (there are ways around that), but you can stick with
             | libraries that do not break their ABI. You can use ABI
             | Laboratory's tracker to check that[1]. For example notice
             | how the 3.x branch of Gtk+ was always compatible[2] (there
             | is only a minor change marked as breaking from 3.4.4 to
             | 3.6.0[3] but if you check the actual report it is because
             | two internal functions - that you shouldn't have been using
             | anyway - were removed).
             | 
             | [0] https://i.imgur.com/YxGNB7h.png
             | 
             | [1] https://abi-laboratory.pro/index.php?view=abi-tracker
             | 
             | [2] https://abi-
             | laboratory.pro/index.php?view=timeline&l=gtk%2B
             | 
             | [3] https://abi-
             | laboratory.pro/index.php?view=objects_report&l=g...
        
         | garaetjjte wrote:
         | >C and C++ development on Windows is great. No sanity is
         | needed.
         | 
         | C++ is bearable (except the bloated piece of crap that is
         | Visual Studio). but C is almost nonexistent. For many years
         | their compiler lagged in standardized C features (this only
         | somewhat improved recently) and you cannot use vast majority of
         | system APIs, which use COM interfaces.
        
           | formerly_proven wrote:
           | You can use COM from C... it's just even more painful.
        
             | ziml77 wrote:
             | Exposing a COM object from C is even worse than consuming
             | one because you need to manually implement the
             | polymorphism. I did it from Rust once in a toy project; it
             | was certainly interesting making it work, but I would never
             | want to do that in a production application.
        
         | xpressvideoz wrote:
         | > avoids entire classes of security issues that the Unix
         | approach has.
         | 
         | I wonder what these might be. You mean potential race
         | conditions regarding file operations?
        
           | torginus wrote:
           | When you open a file in Linux, you hold on to the reference
           | of the underlying inode, which means if you load myLib 1.0,
           | then update to myLib 1.0.1 using apt, then all the previously
           | open programs will be stuck on the old version. This is a
           | security issue at best, since unless you restart, there's no
           | way of making sure nobody uses the old lib anymore, but more
           | frequently a source of crashes and bugs, since myLib 1.0 and
           | 1.0.1 might not be perfectly compatible. If I update Ubuntu,
           | Chromium is almost 100% guaranteed to crash, (since the newly
           | started processes use different lib versions), but I've seen
           | other crashes as well.
           | 
           | In summary, I can't recommend you continue using your Linux
           | machine after an update without a restart, since you are open
           | to an entire category of weird bugs.
        
             | ajuc wrote:
             | In Windows you have to restart anyway, so your problem
             | seems to be that you have a choice in Linux?
        
               | [deleted]
        
               | zamadatix wrote:
               | Both have updates in which you do or don't need to
               | restart to apply them. Both also have methods of
               | hotpatching all the way to the kernel level depending how
               | much it's worth it to someone as well.
        
             | blibble wrote:
             | there are various tools that will tell you if you have old
             | libraries in use by walking /proc
             | 
             | and the Chrome thing sounds rather strange as I thought
             | Chrome forked processes from a "zygote" (a prototype
             | process) rather than re-exec'ing() the binary (which should
             | retain the handle to the deleted library inodes)
             | 
             | not to mention the shared library naming scheme should
             | prevent this sort of incompatible change from occurring
        
         | rileymat2 wrote:
         | A lot of the article is about string handling, I very much
         | agree with that part of the article, having worked on a lot of
         | legacy code built over decades before the introduction of UTF-8
         | compatibility.
         | 
         | It gets worse with that old code if you try to share modules
         | between windows and Linux applications.
         | 
         | Additional complications come from trying to support TCHAR to
         | allow either type of char for libraries.
         | 
         | Anyway, I have ended up supporting monstrosities of wstring,
         | string, CString, char *, TCHAR mushed together, constantly
         | marshalled converted back and forth.
         | 
         | And more: https://docs.microsoft.com/en-us/cpp/text/how-to-
         | convert-bet...
        
         | pjc50 wrote:
         | > how the Windows Console is a fundamentally different beast
         | than a terminal
         | 
         | Yes, and almost entirely in ways that are bad.
         | 
         | I think Microsoft have partially recognised that they're tied
         | to compatibility with a set of choices that have lost the
         | popularity wars and now look wrong. That's why they've produced
         | the two different sorts of WSL, each of which has awkward
         | tradeoffs of its own. And Windows Terminal to replace the
         | console. But eventually I think they may be forced to:
         | 
         | - drop \ for /
         | 
         | - switch CRLF to LF as the default
         | 
         | - provide a pty interface
         | 
         | - provide a C environment that uses UTF-8 by default
         | 
         | It's been weird working with dotnet core and seeing the "cross
         | platform, open source" side of Microsoft, who develop in a
         | totally different style. It's like watching a new ecosystem
         | being built in the ruins of the old.
        
           | zamadatix wrote:
           | The PTY side has been covered for a couple of years now with
           | the introduction of ConPTY.
        
           | zvrba wrote:
           | > drop \ for /
           | 
           | API calls accept / as path separator (and interpret it
           | correctly). Shell is a different beast though.
        
             | tcfhgj wrote:
             | I just tested in PS and found that it eat's / as well
        
               | [deleted]
        
             | vbezhenar wrote:
             | cmd accepts /, but you need to enclose path into quotes,
             | otherwise it tries to interpret it as an option switch.
             | 
             | So you would also need to rewrite all command line
             | utilities to use something like `ipconfig --all` instead of
             | `ipconfig /all`.
        
         | burntoutfire wrote:
         | > C and C++ development on Windows is great. No sanity is
         | needed.
         | 
         | So, you might as well be insane? :D
        
         | charcircuit wrote:
         | >Microsoft robustly caters to backwards compatibility.
         | 
         | This includes bugs too. I ran into an undocumented bug in
         | select(1) IIRC that they couldn't fix since it would break
         | backwards compatibility. I spent like a day trying to figure
         | out why my program wouldn't work correctly on Windows.
        
         | rossy wrote:
         | > _I half empathize. I 'd empathize more if (as the author
         | notes) you couldn't just use MinGW for ports, which has the
         | benefit that you can just use GCC the whole way down and not
         | deal with VC++ differences_
         | 
         | MinGW GCC doesn't make a difference to the article. It uses the
         | same C runtime library as VC++ and has the same problems with
         | defaulting to ANSI codepages and text-mode streams. In fact, as
         | far as I know, there is no native open-source alternative to
         | the VC++ runtime that isn't a full alternative programming
         | environment like Cygwin.
        
       | habibur wrote:
       | If I were to develop native Windows app now, I would still go for
       | C-Win32-GDI, instead of sorting through all those jungle of
       | stacks that had been coming and going in the last 20 years.
        
         | zenlot wrote:
         | I'd choose Delphi instead for native Windows apps. This is
         | where it still shines.
        
         | topspin wrote:
         | The classic Win32 GDI API isn't the worst thing imaginable. It
         | has been the basis of untold amounts of successful GUI software
         | and it still works, although much of the latest capability of
         | Windows is hard to reach using it.
         | 
         | The best GUI development experience I had on Windows aside from
         | that was WTL/ATL. I kept hoping for a long time that this
         | framework would reemerge as a first class GUI platform on
         | Windows. I think Microsoft missed a tremendous opportunity by
         | neglecting it. It actually made writing COM components
         | enjoyable and appealing.
        
         | tored wrote:
         | I can recommended PureBasic. You can call win32 API directly
         | from PureBasic if you need to. Easy to both build and call
         | static and dynamic libraries.
         | 
         | https://www.purebasic.com/
        
         | Koshkin wrote:
         | And with Wine you have some hope for portability.
        
         | spaetzleesser wrote:
         | qt would be a good candidate too.
        
         | oneplane wrote:
         | Unless you're writing something low-level like a driver or
         | representation engine (game engines or CAD/CAM or something
         | like that), why would you still have to write native Windows
         | applications?
         | 
         | I do see how a native application generally behaves and
         | performs better, but it's a whole lot of extra work vs. a less-
         | than-native application. I'd even opt for a generic backend
         | (say, Rust or Go based) and simply having the 'interface' be
         | OS-native.
        
           | pjmlp wrote:
           | Life sciences laboratory devices, DAW, factory automation,
           | air gaped dashboards, for some examples.
        
             | oneplane wrote:
             | So essentially the representation engines (specialised
             | science on Windows, DAW on Windows), but factory automation
             | or air gapped dashboards, I doubt either needs Windows or
             | 'native' applications on a desktop? Maybe a Windows-based
             | HMI or something, but other than that I haven't seen any
             | implemented like that.
             | 
             | Factory automation at TSMC and the likes is mostly just
             | Java, web and webbased interfaces all in a closed network.
             | Same for most modern logistics factory automations.
             | 
             | Classic PLC-based HMI interfaces from Siemens and the likes
             | do still come with Windows as a dependency, but those have
             | normal HTTP interfaces as well. Besides, this is such a
             | niche with so much money going around they hardly depend on
             | the ability to work inside of Microsofts limits. Calls into
             | private APIs galore, hence the limits on OS patches and
             | upgrades that might break those undocumented interfaces...
        
               | pjmlp wrote:
               | Most drivers for such hardware are based on DLLs or COM,
               | and they aren't going to change any time now.
        
           | no_time wrote:
           | Pride in one's craft. It starts to make a lot of sense when
           | you are optimizing for anything other than profit.
        
           | gefhfffh wrote:
           | You can develop native windows apps in Rust these days - even
           | through the new old win32 APIs
        
             | oneplane wrote:
             | Technically anything with a bridge or FFI would be native
             | enough I suppose ;-)
        
             | topspin wrote:
             | You can, and it's actually more pleasant to deal with than
             | Rust+GTK on Windows, if only for the compile time.
        
         | jcelerier wrote:
         | If were to develop a native Windows app 20 years ago, I'd have
         | picked Qt, in these 20 years I'd have relatively simple changes
         | to make and in exchange I'd get portability to many more places
         | and great performance
         | 
         | https://www.qt.io/blog/2018/05/24/porting-from-qt-1-0
         | 
         | I'd do the same today, definitely !
        
       ___________________________________________________________________
       (page generated 2021-12-31 23:01 UTC)