[HN Gopher] C Macro Reflection in Zig
___________________________________________________________________
C Macro Reflection in Zig
Author : jstrieb
Score : 268 points
Date : 2024-07-30 06:57 UTC (16 hours ago)
(HTM) web link (jstrieb.github.io)
(TXT) w3m dump (jstrieb.github.io)
| skywal_l wrote:
| @cImport is on the chopping block though [0]. You will still be
| able to import c files but it will require a little more work.
| This is because they want this functionality out of the language
| so they can remove libclang dependency.
|
| [0]: https://github.com/ziglang/zig/issues/20630
| flohofwoe wrote:
| It would actually be nice if the translate-c build system step
| would also allow some restricted symbol transformation (at
| least stripping the 'namespace prefix' from C library symbols).
|
| For instance Odin allows to define a 'link_prefix' for C APIs
| which is then stripped from the imported symbols:
| @(default_calling_convention="c", link_prefix="sg_")
|
| This causes name transformations like:
| sg_setup() => setup() sg_shutdown() => shutdown()
|
| ...maybe even convert from common case-conventions (like
| snake-, camel-, pascal- case etc...) to Zig's naming convention
| so that imported C interfaces don't look so alien relative to
| native Zig interfaces.
| Cloudef wrote:
| From the issue
|
| > As a consolation prize, the TranslateC build step can be
| enhanced with advanced settings, such as namespace stripping
| and validation of existing bindings. Since changes to this
| don't require changing the language, it's OK if the scope &
| complexity increase to some extent.
| o11c wrote:
| > common case-conventions
|
| Unfortunately, we must not forget forget ABOMINATIONCase and
| NAMESPACED_PascalCase (we could also generalize this to _any_
| switch from one convention to another after the first word).
| I 've found they usually are, in fact, identifiable and
| roundtrippable. I've found the following usually works (it
| fails for multi-word prefixes or non-leading exceptions, and
| of course single-word identifiers are ambiguous):
| count and strip all leading, then trailing, symbols (in some
| languages this is not limited to underscore but said
| languages usually need special handling anyway) for
| every chunk separated by underscore, space, or hyphen (this
| may be nothing): if the chunk either has no uppercase
| or has no lowercase, simply use it as a word. Otherwise:
| for every sliding-window pair of letters (c, d) in the chunk:
| if c is uppercase: if d is lowercase, or d is a
| digit and there is lowercase elsewhere: start a
| new word before c
|
| Then for the words-to-convention direction:
| space and kebab case don't have any good answer for affixes
| AFAIK. Otherwise, restore at least the leading underscores
| (trailing underscores are usually keyword-avoiding) for
| snake and screaming case, be sure to prepend an underscore if
| the *result* would start with a digit for camel
| variants, prepend an underscore to each *word* that starts
| with a digit. But if there were originally more than 1
| leading underscores, use those instead for the first word.
| flohofwoe wrote:
| I mean, there can always be a function on the TranslateC
| step which maps 'special case' names (or even translate
| them to an entirely different name, for instance when
| there's collisions with Zig reserved keywords):
| translateSpecialCaseNames(.{ .{ .src =
| "ABOMINATIONCase", .dst = "case" }, .{ .src =
| "NAMESPACED_PascalCase", .dst = "pascalCase" }, });
|
| ...in my own language bindings generator, being able to
| define such special case mappings is actually quite
| important, mainly for handling that situation where an
| automatic mapping would result in a reserved keyword.
| o11c wrote:
| Reserved words really shouldn't require manual care;
| "list of keywords in X language" is really easy to handle
| so you can just append an underscore.
|
| I do think that namespaces need to be semi-manually
| managed though (likely only at the project level), since
| often there are things that look like a namespace but
| shouldn't be treated like one, and it's not always
| obvious from a single identifier how many words should be
| treated as the namespace in some styles.
|
| One special case is that sometimes C-ish libraries have
| class-likes like {Foo, FooBar, FooBaz} where the desired
| mapping is {foo.Foo, foo.Bar, foo.Baz}.
| jay-barronville wrote:
| While I understand the reasoning, I think this is one of the
| most disappointing decisions by the Zig team.
|
| One of the main reasons I took Zig seriously was their C
| interop story--as someone who loves C and dislikes almost every
| implementation of C interop and FFI I've used in other
| languages (Rust is a notable exception to this), I was pretty
| much sold on Zig when I was able to, in a total of < 3-ish
| hours, (1) implement a complete Zig wrapper over a C library I
| wrote without introducing any overhead, (2) build a Zig program
| using the wrapper, and (3) cross-compile the program,
| statically, producing single binaries for 5 different
| targets...Linux (amd64, arm64), macOS (amd64, arm64), and
| Windows (amd64), ALL from one laptop using a single Zig
| executable and some simple flags. This was C interop and
| productivity I've never experienced before.
|
| I respect Andrew a lot (I think he's pretty brilliant), so I
| hope this turns out to not be as bad as I think it'll be for
| those of us who love Zig for what brings to the table for
| programmers who are biased toward C.
| flohofwoe wrote:
| The translate-c build system step and wrapping the output in
| a Zig module is currently about 10 lines in build.zig, and I
| guess this could be reduced further by merging those two
| steps into a single step.
|
| I think that's an acceptable compromise.
|
| Especially for C libraries which require configuration via
| preprocessor defines or compilation flags, the build.zig way
| is a lot cleaner than the @-builtins that are currently used
| (IMHO).
| Cloudef wrote:
| How I see is that the only thing that changes is that you
| can't do @importC anymore. You'll instead do something in
| build.zig that produces a module which you can then
| addImport("my-c-lib", generated_module); which you then
| @import("my-c-lib"); in your zig code as you would with
| @cImport.
|
| This does not seem bad in paper. One thing that does worsen
| with this is that in @cImport you could also comptime define
| preprocessor macros which was really cool, now that would
| have to be handled by build.zig I guess.
| jay-barronville wrote:
| This makes the experience more similar to Rust (which I
| don't think is bad--it's just not as unique, smooth, and
| impressive as the current Zig experience).
|
| I've been able to convince C programmers to try out and use
| Zig just due to this unique ability alone, and to be clear,
| getting C programmers to seriously consider any language
| other than C is generally very difficult!
|
| Having to consider another build system (with its own
| semantics), which the current Zig experience doesn't
| require, changes the experience much more substantially
| than I think the Zig team realizes.
| flohofwoe wrote:
| > This makes the experience more similar to Rust
|
| The big difference to the Rust ecosystem (or rather the
| 'cc' crates.io package which AFAIK is the current
| standard solution) is that there will be a Clang
| toolchain package with integrated cross-compilation
| headers and libraries that is used across all platforms
| instead of relying on a "platform C/C++ compiler
| toolchain" - which is the actually brittle part:
| different compilers, linkers and platform SDKs used on
| different platforms).
|
| Ideally that same integrated Clang toolchain package used
| and provided by Zig could also be used by Rust to improve
| the C/C++/ObjC cross-compilation situation (similar to
| how the Zig toolchain is sometimes already used for this
| purpose).
| jay-barronville wrote:
| > The big difference to the Rust ecosystem (or rather the
| 'cc' crates.io package which AFAIK is the current
| standard solution) is that there will be a Clang
| toolchain package with integrated cross-compilation
| headers and libraries that is used across all platforms
| instead of relying on a "platform C/C++ compiler
| toolchain" - which is the actually brittle part:
| different compilers, linkers and platform SDKs used on
| different platforms).
|
| Yes, this is a very good point. Zig remains unique and
| impressive in that sense. The fact that Zig compiles the
| correct libc and other system libraries on demand is
| actually another one of those, "How come no other
| language considered doing this before Zig?!?"
| steveklabnik wrote:
| I truly wish that Rust would steal this from Zig, but I
| haven't heard any actual interest in it from the project.
| Oh well. I think it's a real missed opportunity.
|
| https://crates.io/crates/cargo-zigbuild exists though.
| jeltz wrote:
| Having worked with Rust I would say that is bad. @cImport
| is way better than the C introp in Rust.
| throwawaymaths wrote:
| You will probably be able to do it from the command line
| too (for build-exe, run, etc).
| jll29 wrote:
| This sounds amazing, and it's great that tooling is so strong
| of some "new kids on the block" (Zig, Rust), even better than
| C.
|
| With hindsight, it is strange that the C community, with all
| the people and money behind it (and what scale!) never even
| managed to build a proper packaging manager (okay, there's
| now Conan, but that came from Python guys).
|
| But then, there even still isn't a perfect C string library
| around (something that would combine GLib, SDS, ICU, say, and
| then standardize it in C2038).
|
| [1] Hanson's C: Interfaces & Implementations (CII) - Str:
| https://cii.s3.amazonaws.com/book/pdf/quickref.pdf
|
| [2] ICU - https://icu.unicode.org
|
| [3] SDS - https://github.com/antirez/sds
|
| [4] GLib - https://docs.gtk.org/glib/struct.String.html
| flohofwoe wrote:
| The interesting thing is that the Zig build system _could_
| be implemented in a C /C++ compiler without any language
| changes. All that's needed is that (for instance) Clang
| would have a new option `clang build` which looks for a
| build.c/cpp file, compiles that into an executable and runs
| it.
|
| The actual build system functionality is 'just' an
| extension to the stdlib.
| pjmlp wrote:
| It could, but then it would be tied to that specific
| compiler and the platforms it supports.
|
| So is the mess of ISO defined languages, where compiler
| toolchains are an abstract concept.
|
| Also a good point to note that OpenGroup and POSIX never
| bothered to standardise UNIX package management.
| flohofwoe wrote:
| Yeah, just Clang doing its own thing would be useless. It
| would have to go through the C and C++ committees, at
| least for the stdlib parts (and this is basically the
| show stopper for the idea unfortunately).
| fxtentacle wrote:
| vcpkg + CMake ?
|
| It can compile almost any dependency on demand, even doing
| cross-compilation. And it's used by at least Microsoft and
| Google.
| flohofwoe wrote:
| Such a setup includes two complex tools from two
| different parties plus a different C/C++ compiler
| toolchain per platform and platform SDKs (at least GCC,
| Clang (plus its Apple flavour) and MSVC). All those tools
| working together flawlessly at any given time is a minor
| miracle.
|
| In Zig all those things are in the same toolchain
| install, which is a a single executable plus a bunch of
| platform-system-headers and -libraries, all under a
| single version number and trivially downloadable as a zip
| archive which works right after unzipping without setting
| up paths or running an 'installer'.
| bluGill wrote:
| > With hindsight, it is strange that the C community, with
| all the people and money behind it (and what scale!) never
| even managed to build a proper packaging manager (okay,
| there's now Conan, but that came from Python guys).
|
| Package managers are a lot more complex than people
| realize. Every attempt I've seen in every language has
| significant lacks for common real world cases.
|
| Most commonly they assume all the world is their language.
| Very commonly they want to take over all package management
| but don't have a good easy story for working with the OS
| package manager (I know Windows doesn't really have a
| package manager - but you still need to interoperate with
| it!). Those are big issues anyone in a complex project will
| face in the real world, there are also lots of little warts
| that will bite you.
|
| Yes package managers are nice on your trival project.
| However they all get in the way in your non-complex project
| - some more than others.
| greenavocado wrote:
| Weird take. Does pip have to interface with the Windows
| or iOS package managers? No. Yet it's wildly successful.
| bluGill wrote:
| > Does pip have to interface with the Windows or iOS
| package managers? No. Yet it's wildly successful.
|
| Successful I agree. I have issues on any system I use it
| on because now I have the package installed by PIP and
| the package installed by my OS package manager - slightly
| different.
| jordanozang wrote:
| If you use pip without protection, it will gladly and
| malevolently mess up your system. Every Python user
| learns quickly about the virtual environment work around.
| Various distributions (e.g. through Homebrew on Os X,
| Arch Linux, Ubuntu Linux) ship pip without the ability to
| make system-wide installations (externally-managed-
| environment). Even on Windows, where there is no
| standardized package management system, doing a pip
| install will place a bunch of dlls in the system's PATH
| that could get in the way of any program on your system.
|
| The anti-solution of ignoring the problem is what got us
| here.
| Joker_vD wrote:
| Why would anyone want to integrate with the OS package
| manager? Windows, as you've said yourself, doesn't even
| have one (and thank goodness for that) while on Linux,
| the distributed packages are normally about 2 to 4 years
| out of date -- unless you discover and use specific 3rd-
| party repositories at which point what's even the point
| then? Just use the language's
| CPAN/PyPI/Hex/Crates.io/etc. analogue.
| bluGill wrote:
| > Why would anyone want to integrate with the OS package
| manage
|
| Because if they don't integrate you end up with several
| different versions of the same package installed. When
| you program grabs the wrong version how do you fix it.
| Now what if you are in support trying to help a customer.
|
| > on Linux, the distributed packages are normally about 2
| to 4 years out of date
|
| Maybe you need to find a different distribution. Some
| make it a point to be out of date. Some make it a point
| to be up to date.
| uecker wrote:
| In the unix world we use distribution package managers.
| This has many advantages, including security updates, some
| robustness against supply chain attacks, large-scale
| integration. All this language-level packaging systems are
| a mistake in my opinion.
| Laremere wrote:
| See these posts on the LLVM issue by Andrew. They clearly
| state that this functionality isn't going anywhere, just the
| method of achieving said functionality is changing:
|
| https://github.com/ziglang/zig/issues/16270#issuecomment-161.
| .. https://github.com/ziglang/zig/issues/16270#issuecomment-1
| 61...
| ajnin wrote:
| Not involved with Zig at all, but this comment is a bit
| concerning :
|
| > This is not the first controversial change I have made to
| the Zig project, and it won't be the last. I have a vision,
| and I know how to execute it. People are often surprised by
| what Zig has accomplished, and they wonder why other
| projects have not done what Zig does. Well, you are seeing
| the magic right now. I ignore the peanut gallery and do
| what I know is right, while taking care of my users' needs
| at the same time. If you don't understand now, you will
| understand once this plan unfolds. By that time it will
| seem obvious in hindsight.
|
| He's probably brillant and all but this ... feels like
| hubris.
| JasonSage wrote:
| Reading that comment for the first time just now, and I
| love that. More power to them.
| BiteCode_dev wrote:
| Or very high confidence backed up by experience and
| skill, expressed through an honest personality.
|
| In a world of humble bragging and cheap talk, I find it
| refreshing.
| carapace wrote:
| Don Quixote or St. George? Only time will tell. Meanwhile
| the code works.
| acedTrex wrote:
| Wow, that actually makes me want to look into zig a lot
| more. so many projects, rust included, get bogged down in
| design by committee and half baked decisions that please
| no one.
| bunderbunder wrote:
| Agreed. Andrew Kelley's ability to have, communicate _and
| maintain_ a clear and consistent vision is one of the
| most refreshing things about Zig. I don 't actually use
| it, but this might actually be the main thing attracting
| me to it.
|
| Plenty has already been said about design-by-committee
| and relying overmuch on user feedback, but one thing that
| doesn't get mentioned as often is that this approach
| tends to transform additive bias[1] from a cognitive bias
| into an iron law. Once you let that happen, you're on a
| relatively short and slippery slope to having a kitchen
| sink language. And one refreshing thing about Zig is
| that's it's clearly working very hard at _not_ becoming a
| kitchen sink language. I 'm not sure I can say the same
| about most other newer systems programming languages.
|
| That doesn't mean having a BDFL is all kittens and
| rainbows, and I'm sure Andrew has made plenty of
| mistakes. But I've also never seen any indication that
| he's acted out of anything other than good faith. That
| last paragraph is possibly the closest I've ever seen to
| him saying something arrogant, and I see it as the
| exception that proves the rule. Finding such a tactful
| way to remind people that this is a BDFL project and he's
| the BDFL could not have been easy, and I imagine he put a
| _lot_ of care into crafting that paragraph.
|
| 1: https://www.scientificamerican.com/article/our-brain-
| typical...
| nkozyra wrote:
| I agree that letting the community completely dictate
| direction is a bad idea, but so too is being so dogmatic
| and idealist that you ignore the feedback.
|
| Rust definitely swayed more to the former than I'd have
| liked, but you also have Go as a counterexample where
| generics were dismissed for a decade+ in response to user
| feedback and then kind of :shrug: ok fine we'll add
| generics.
| eyelidlessness wrote:
| I simultaneously understand why that comment gives you
| pause, and find comfort in seeing such a clear expression
| of vision.
|
| As someone who often thinks several steps ahead about
| where I want to take a project, I find it's just as often
| difficult to communicate that vision at the level of
| detail necessary to establish a shared understanding of
| what those steps mean, and how various apparent minutiae
| come together to make them all valuable together.
|
| I would be lying if I said I don't wish I shared this
| particular hubris, and the corresponding expectation that
| execution will be sufficient to bolster any trust
| challenged along the way.
| jay-barronville wrote:
| > He's probably brillant and all but this ... feels like
| hubris.
|
| I don't think it's hubris, because Andrew's results speak
| for him, but it's certainly alienating, to be honest.
|
| Although I understand the struggle of having to
| prioritize opinions and perspectives, it comes across
| like Andrew only values the opinions and perspectives of
| very specific folks, whom he often calls out.
|
| Here's what I mean: I love Zig and I write a lot of Zig
| code, especially within the past year (almost daily), but
| none of the Zig code I've been working on is publicly
| available or open-source (although I hope I can open-
| source various components soon, fingers crossed). I've
| gained a lot of valuable experience with Zig--including
| successfully convincing folks (mainly C programmers) to
| use it who wouldn't have tried it otherwise. When I read
| these interactions, even though I have thoughts I'd like
| to share as a committed user who wants to see the project
| succeed and gain mainstream adoption, I get the feeling
| that my thoughts aren't welcome since I don't have a huge
| Zig project or something, so I just keep my thoughts to
| myself. Andrew seems to mostly care about feedback from
| the creators of Bun, TigerBeetle, etc., which, if I'm
| correct, is fine (it's his project and therefore his
| right), but I imagine there are plenty of users like me
| who aren't just part of "the peanut gallery" yet staying
| out of it to avoid the drama.
| dangets wrote:
| This type of stance is what de-popularized the Elm
| language.
|
| Don't get me wrong - I wish the best for both languages
| and am thoroughly impressed by the work of their
| creators. I can see that it must be a hard thing to
| balance.
| kasajian wrote:
| Sounds like damage control. I have to say, for a brilliant
| guy, andrewrk knows nothing about marketing. The fact that
| the Zig project can make this significant of a change to
| their core-value because "trust me i know what I'm doing",
| makes it impossible (for now) to rely on this in any type
| of a widely-deployed Enterprise setting. This just made the
| highly risky move of moving to Zig make it darn near
| impossible.
|
| What he should have done is announce a project at the same
| time that will maintain the current developer experience,
| even if that project is not part of the zig foundation. The
| developer doesn't care about how he builds zig. They want
| 1) download 2) use. It doesn't matter from where. If today
| it's directly from zig, and tomorrow it's from elsewhere to
| download a combined package, that 's all the devs needed to
| hear.
| throwawaymaths wrote:
| Wait what is controversial here? Removing llvm as a
| dependency and making it a (probably default available)
| plugin instead? Seems "obviously good", if you ask me.
|
| Weird machinations around projects that are and aren't
| (but are privileged because he's the creator) part of the
| zig foundation would be more concerning, quite frankly.
| flohofwoe wrote:
| Unfortunately there's a lot of people on the internet who
| haven't even used Zig nor plan to use it anytime in the
| future and who just enjoy to create drama by amplifying
| any decision with a hint of controversy around it (also
| see the 'unused variables are errors' drama which turned
| out to be a non-issue after it was actually implemented).
|
| Unrelated to Zig, it's the exact same thing with "WASM
| can't access the DOM" btw, comes up everytime when WASM
| is in the news, but is a complete non-issue in practice
| for anybody actually using WASM, and I'm sure each
| popular software project has at least one such 'drama
| issues'.
|
| The 'LLVM divorce' has been announced waaaay ahead (maybe
| years) of any actual steps to make that happen, for a
| language ecosystem that's still unstable anyway, and with
| the promise that a solution will be in place before LLVM
| is actually kicked out.
|
| Not sure what else could have been done better, and as
| other have said, this sort of decision making process is
| much preferable to a committee approach.
| jeltz wrote:
| The LLVM divorce has also gotten criticism since it first
| was announced and we have so far not seen any complete
| solution. Maybe we will land in one but if people did not
| voice their concerns there is no reason to think such a
| solution would be found.
| throwawaymaths wrote:
| What is there to criticize though? What "solution" is
| necessary?
|
| LLVM is not and was never going away as a compiler
| backend, it will just not be the default one and you will
| be able to compile zig without it (though in practice
| everyone will for prod releases)
| kasajian wrote:
| The fact that WASM requires a JS is a marketing fail and
| misses what could have been a marketing opportunity to
| make the claim, "finally an alternative to JavaScript".
|
| In this case, this is not a non-issue. If you look at the
| original github issue, it does a lot of damage, followed
| by a lot of confusion, followed by a damage-control post
| that shouldn't have been required if it the original
| issue was written with more care. It wasn't, because the
| marketing aspect of Zig was not the focus -- the
| technical issue was. So it blew up. Hopefully it'll be a
| lesson learned, but I suspect it isn't. It will take 20
| more of such incidents before it sinks in.
|
| As far as it was "announced years ago", I don't see how
| that matters. The people who are seeing the issue now,
| and this discussion weren't there to see the announcement
| years ago.
|
| But I do understand what you're saying. You're point is
| that the onus is on the the reader to the do their
| research before overreacting. That's a perfectly fine
| position. I have a counter opinion which is that the
| person making the statement / claim / annoucement, simply
| be understanding of the implication of their statements.
|
| This thing blowing up should not have been a surprise to
| anyone. Sounds like it would have been to you, so the
| fact that it blew up is evidence that you would have
| misjudged. Unless you also agree that the initial message
| should could have been better worded, in which case, what
| exactly are you disagreeing with?
| throwawaymaths wrote:
| You have to admit that "divorce" was not really a good
| metaphor, though it did get eyes on the drama.
| pharrington wrote:
| Zig's not at version 1.0.0 yet. Yes, it would be very
| irresponsible to use current-day Zig in a widely-deployed
| Enterprise setting. The release notes explicitly
| acknowledge Zig is currently immature, and is currently
| only suited to people willing to participate in the
| language development process.
| brabel wrote:
| > as someone who loves C and dislikes almost every
| implementation of C interop and FFI I've used in other
| languages (Rust is a notable exception to this),
|
| Have you tried D? It can import C files as if they were D
| modules: https://dlang.org/spec/importc.html
|
| Basically, if there's a `hello.c` file next to your D file,
| you simply import it with: import hello
|
| And use the functions it provides. You can also import only a
| subset of it, of course: import hello:
| square;
|
| Or rename the import: import hi = hello;
|
| The C stdlib is exposed by D's stdlib as if it were a D
| library: https://dlang.org/phobos/core_stdc_assert_.html
|
| C libraries (header files) can be compiled to D and then used
| as D modules as well, see https://github.com/jacob-
| carlborg/dstep
|
| Is that as good as Rust?
| jay-barronville wrote:
| > Have you tried D?
|
| I tried D years ago (at least 5 years ago, I think), but I
| don't remember experimenting with the C interop.
|
| Your explanation sounds intriguing though. And a couple
| pretty smart folks I respect have talked about D too. So
| thanks for bringing it up. I'm going to make some time to
| experiment with it again some time soon.
|
| > Is that as good as Rust?
|
| Franky, although I don't have firsthand experience with D,
| your explanation and example make the D C interop
| experience sound actually better than Rust's. It seems more
| similar to Zig.
| brabel wrote:
| I think the feature that allows importing c, called
| "importC", is newer than 5 years. I think they may have
| "copied" it from Zig :D they definitely are trying to not
| "fall behind" Zig and keep making the language better.
| With DMD, you can cross compile just as with Zig, but
| only to object files as the linker is not multi-
| platform... so I am experimenting with using Zig's linker
| to "finish" the job. Unfortunately, Zig is not being able
| to link Phobos, the D stdlib, for reasons I don't
| understand yet.
| 1980phipsi wrote:
| D has made some improvements on C interop with importC, if
| you want to check that out:
| https://dlang.org/spec/importc.html
| throwawaymaths wrote:
| What's the problem? @cImport is becoming just @import.
| kbolino wrote:
| @cImport works without build.zig and even with build.zig
| requires no special configuration (ignoring linking).
|
| As it is currently described, @import of C will require
| build.zig and specific configuration therein.
| jeltz wrote:
| And form my experience from Rust that is much less
| ergonomic. Maybe Zig will do it better than Rust but who
| knows?
| samatman wrote:
| build.zig is on its way to being essential.
|
| I consider that an appropriate development. Binaries need
| to be built, this should be integrated with the rest of
| the system in any modern language.
|
| It's not incompatible with using something like CMake or
| Ninja either, it just puts certain responsibilities
| inside of build.zig. Where they belong.
| throwawaymaths wrote:
| I don't think that's the case. In general you can set up
| @import modules from the command line, and I'm not 100%
| sure but I think build.zig generally just templates a
| command line call anyways.
| kbolino wrote:
| I don't think this DSL is finalized yet, but you can see
| on a linked issue what the build.zig to support @import
| of C looks like on nightly: const
| translate_c = b.addTranslateC(.{
| .root_source_file = b.path("src/c.h"),
| .target = target, .optimize = optimize,
| }); exe.root_module.addImport("c",
| translate_c.createModule());
|
| https://github.com/ziglang/zig/issues/20648
| mk12 wrote:
| It won't require build.zig, you'll just have to run zig
| translate-c on the C file. Andrew's comment here[1] says
| that @cImport is basically @import + the compiler
| implicitly running translate-c for you. There was some
| discussion of removing the translate-c subcommand as well
| (which _would_ force you to use build.zig), but I don 't
| think it's been decided to do that.
|
| [1] https://github.com/ziglang/zig/issues/20630#issuecomm
| ent-225...
| jay-barronville wrote:
| > What's the problem? @cImport is becoming just @import.
|
| You're oversimplifying what's actually a significant
| change.
|
| Right now, I can do the following:
|
| 1. Download a prebuilt Zig release [0], on a fresh computer
| (zero prerequisites).
|
| 2. Implement a C library foo via foo.h and foo.c.
|
| 3. Compile foo.c into an object file foo.o via `zig cc`,
| using standard GNU-compatible compiler flags, for virtually
| any of the common (and even not-so-common) compilation
| targets.
|
| 4. Implement a Zig program bar via bar.zig.
|
| 5. Directly import foo.h into bar.zig via `@cImport` and
| use the C API as if it was Zig code.
|
| 6. Compile bar.zig and foo.o into a statically-linked
| executable baz via `zig build-exe`, for virtually any of
| the common (and even not-so-common) compilation targets.
|
| No knowledge of the Zig build system and its semantics
| necessary. This is one of the most attractive aspects of
| Zig for a C programmer. I've gone through these exact steps
| with C programmers who thought Zig seemed interesting in
| theory but just didn't want to have to learn a new
| ecosystem, build system, etc. The moment I showed them how
| quickly they could get up and running with Zig (and test it
| out with C code), without even having to install anything,
| it suddenly was impressive enough to experiment with.
|
| The build system requirement may seem minor if you're
| already a Zig programmer, but it's massive if you want to
| attract C systems programmers.
|
| [0]: https://ziglang.org/download
| throwawaymaths wrote:
| I think someone who doesn't know what they are talking
| about about is asserting a build.zig requirement. I don't
| know for sure, but probably it will work with the command
| line?
| ajnin wrote:
| > remove libclang
|
| So `zig cc` will have to go as well ? I was under the
| impression Zig as a drop-in C (cross-)compiler was one of its
| main selling points.
| flohofwoe wrote:
| See: https://github.com/ziglang/zig/issues/16270#issuecomment
| -161...
|
| The ability to seamlessly compile C/C++/ObjC code within a
| Zig project is extremely important for me as well, but I'm
| fine with that job being delegated to a Zig package and the
| Zig build system.
| deagle50 wrote:
| It seems the build system has gotten enough traction and Andrew
| is going for broke to enshrine its place in the C space. I
| wouldn't bet against him.
| samatman wrote:
| It will require a little more work in a trivial way, but not in
| a meaningful way.
|
| What's happening is that C imports are moving to the build
| system, instead of being a compiler builtin. It's part of
| making LLVM and libclang optional for programs which don't use
| it, but the use case of building C programs, and integrating C
| libraries with Zig programs, remains a central design goal.
|
| The build system is relatively new, and a lot of things which
| were originally independent subcommands are being consolidated
| into the build system.
|
| There's a sort of ambient impression that "Zig won't support C
| anymore" floating around, I'm not sure from your post whether
| you have that impression or not, but it isn't even vaguely
| true.
|
| It just means that importing C libraries will be a build step,
| and not something you write directly into the relevant source
| code. This is not a big deal.
| jay-barronville wrote:
| > It just means that importing C libraries will be a build
| step, and not something you write directly into the relevant
| source code. This is not a big deal.
|
| It 100% is a big deal. I explained this in another comment
| [0].
|
| [0]: https://news.ycombinator.com/item?id=41111445
| throwawaymaths wrote:
| I think you are operating from a mistaken understanding, as
| responded to in the linked comment.
| jay-barronville wrote:
| > I think you are operating from a mistaken
| understanding, as responded to in the linked comment.
|
| No, I'm not. Respectfully, you're responding to my point
| while admitting in your comment [0] that you don't
| actually know.
|
| If you read the relevant discussions, the conclusion,
| last time I checked, was that there's going to be a build
| system requirement.
|
| [0]: https://news.ycombinator.com/item?id=41111542
| throwawaymaths wrote:
| I "don't know" because zig 0.14 is not released yet and
| anything could happen but I DO know that imports do not
| currently require the build system. And I THINK that's
| because the core parts of the build system (including
| binding imports) are dependent on the command line
| anyways. So I am ASSUMING that property will be invariant
| when the c @import gets implemented, and my "don't know"
| is merely being explicit about that assumption. You are
| the one coming from a place of ignorance here, and your
| refusal to acknowledge that you might be wrong makes me
| suspect your argument is not being made in good faith.
| jay-barronville wrote:
| > You are the one coming from a place of ignorance here,
| and your refusal to acknowledge that you might be wrong
| makes me suspect your argument is not being made in good
| faith.
|
| You're making a lot of "assumptions" when you could just
| read the GitHub issue regarding this change, written by
| Andrew himself, titled "move @cImport to the build
| system" [0].
|
| By the way, please note that I not only write Zig code
| almost daily, I've personally contributed to the Zig
| build system.
|
| [0]: https://github.com/ziglang/zig/issues/20630
| TwentyPosts wrote:
| Andrew (in the linked Github page) answered a question as
| follows:
|
| > Question: "So after this change, is there way I can
| still simply call zig run or do I have to use a build.zig
| file?"
|
| Andrew's answer: "No, this use case will regress."
|
| This in fact literally states that "just" calling "zig
| run" won't be possible anymore, and heavily implies
| you'll need a build.zig file.
| samatman wrote:
| We have different ideas of what a big deal is, clearly.
|
| The idea that C programmers, _C programmers_ , are going to
| start bailing en masse out of the top of the Zig funnel,
| because they have to copy-paste a build.zig gist to get
| started? This is risible.
|
| The complexity has moved to a slightly different place.
| That's it.
| whitehexagon wrote:
| Do we know if this means the Reflection as mentioned in the
| article via @typeInfo will no longer work? or was it anyway
| comptime info? My Zig so far has been SoC level stuff, but
| using something like raylib or glfw is somewhere on my todo
| list, and this example sounds mighty useful. Anyway seems a
| strange thing to remove when Zig has the potential to be the
| new C. Hopefully also as stable for the next 30 years :)
| pbaam wrote:
| It will still work. If you look at the type signature of
| @cImport in the language reference[1], it returns a type just
| as @import. So you can call @typeInfo on it. But instead of
| writing const win32 = @cImport({
| @cInclude("windows.h"); @cInclude("winuser.h");
| });
|
| You will write: const win32 =
| @import("win32");
|
| Where the module "win32" is declared in build.zig.
|
| [1] https://ziglang.org/documentation/master/#cImport
| eska wrote:
| Wouldn't this add at least UINT16_MAX*sizeof(intptr_t) bytes into
| the executable per enum?
| flohofwoe wrote:
| I think the executable will essentially contain a lookup table
| with 2^16 slots and the string data for each macro name
| matching WM_* in Windows.h. But it's hard to come up with a
| better solution since the actually required names are
| unpredictable at compile time. The size of the lookup table
| could be reduced though if the WM_* values occupy a much
| smaller range.
| Cloudef wrote:
| It adds 65536 pointers to the binary. Alternative would be to
| use a hash map. I think if they made function that used inline
| for instead it would optimize to a switch. No need for a LUT.
| fn stringFromMsg(umsg: c_int) [:0]const u8 {
| @setEvalBranchQuota(1000000); inline for
| (@typeInfo(win32).Struct.decls) |field| { if
| (field.name.len >= 3 and std.mem.eql(u8, field.name[0..3],
| "WM_")) { if (umsg == @field(win32,
| field.name)) { return field.name;
| } } } unreachable; // umsg
| is not valid, programming mistake }
|
| godbolt: https://zig.godbolt.org/z/7b73aoosf
|
| In zig-budoux, I also do comptime reflection on cImport struct
| to assert compile time that we won't produce broken runtime
| code
|
| https://github.com/Cloudef/zig-budoux/blob/master/src/c.zig#...
| flohofwoe wrote:
| > ...instead it would optimize to a switch. No need for a
| LUT.
|
| IME there's is no difference in (optimized) code generation
| between an if-else chain, a switch or (like in your example)
| an unrolled for-loop with an if inside. All those high level
| constructs will be optimized into a single lookup table, or a
| combination of multiple lookup tables and binary search to
| select between those. Only if there are absolutely no
| consecutive ranges in the switch-set, a binary search without
| jump tables will be used.
| Cloudef wrote:
| Note that you can't use normal for here as you are
| accessing comptime known variables. Inline for will unroll
| the loop so that comptime constants get resolved for
| testing against runtime variables and then the optimizer
| picks out the best code (often jump tables / switch) to
| generate. You are right though.
| Joker_vD wrote:
| Clang's preprocessor is actually _not_ implemented as a separate
| compilation pre-pass, it 's essentially a part of the lexer and I
| would be willing to bet that gcc uses a similar scheme.
|
| So there is nothing technically impossible about having the
| access to macro names as a compiler-specific extension, it's just
| that there is no much demand for it.
| JonChesterfield wrote:
| Clang prints out things about macro instantiations on the
| semantic error reporting paths. That probably means it has all
| the macro information available already.
|
| It's not probably reflected to the language because C++ fears
| reflection in general and hates macros in particular.
| g15jv2dp wrote:
| > C++ fears reflection in general and hates macros in
| particular.
|
| Macros aren't a particular case of reflection... And at least
| in the way they're done in C++, they're a big source of bugs
| / spaghetti.
| formerly_proven wrote:
| > C++ fears reflection and hates macros
|
| But only wicked gods would banish us from paradise
|
| Why do they fear our power?
|
| Because evil is what they are.
| bluGill wrote:
| Reflection is on track for C++26 so it is completely wrong to
| say C++ fears reflection.
| Joker_vD wrote:
| Reflection proposals have been around at least since 2014,
| so I'd say it's exactly right to say that C++ _fears_ it --
| otherwise it 'd have arrived much sooner.
| bluGill wrote:
| C++ fears getting reflection wrong, which is why it takes
| a long time to get it in.
| 3836293648 wrote:
| C++ fears getting lots of stuff wrong, which is why they
| got rid of good concepts, waited 20 years and then added
| bad concepts
| voidUpdate wrote:
| I really want to like zig, but I've just had some annoying
| problems with it, most of which I think are just a result of it
| not being in 1.0 yet. For example, the recommended way to start a
| project, with `zig init`, has a load of code that I really don't
| need when I just want a bare project to get started. I only
| recently found out that you can just `zig build-exe filename.zig`
| and skip the whole init part. Also I've had a lot of issues
| getting editor integration to work correctly. I've installed the
| VSCode extension but I don't seem to be getting autocomplete etc.
| It is quite possibly just an ID-10T problem though, so I'll
| probably take another look at it some weekend
| flohofwoe wrote:
| Tbf, when coming from the C/C++ ecosystem, these types of
| problems are 'just another Tuesday' (especially for cross-
| platform projects and the official VSCode C/C++ extension).
| voidUpdate wrote:
| Yeah, that's one of the reasons I dislike the C++ ecosystem
| so much and want to like Zig haha
| jeroenhd wrote:
| This is part of the reason why I don't use VSCode for C(++).
| Jetbrains Clion seems to be the best IDE for those languages,
| with Visual Studio (the full fat one, costing a grand, as the
| free version lacks a bunch of features) as a close second,
| depending on what platform you're developing for.
|
| VSCode is great when it works, but in cases like these it
| quickly becomes obvious that it's a hodge-podge of tools
| glued together via extensions and command lines rather than a
| purpose-built IDE.
| markus_zhang wrote:
| I have never used Clion. Can you please share why you
| believe it is the top of the crop? I'm writing a C++/SDL2
| game engine in Visual Studio but I think the IDE is really
| slow and error prone even for a small project. Everything
| just runs so slow. Maybe I need a better machine though.
| Quothling wrote:
| I'm not one to defend VSC as such, but I do think it's fair
| to mention that a lot of the Zig issues have been directly
| with the Zig LSP (zls) and not necessarily with any
| specific editor extension. Though I suppose some of it may
| be worse with VSC as it's often been rather important to
| keep both your Zig and zls versions up-to-date and
| synchronized. I'm not sure how that happens with the VSC
| extension, but if it auto-updates your zls version (which
| it probably does) then it may race ahead of your Zig
| version which might cause problems.
| bobajeff wrote:
| Note for people wanting to use vscode for c or c++
| development. The clangd extension* is provides much better
| code completion and jump to definition compared to the
| default c/c++ extension.
|
| * https://marketplace.visualstudio.com/items?itemName=llvm-
| vs-...
| Cloudef wrote:
| zls should generally work out of the box but I don't use
| vscode, so your mileage may vary. Make sure your zls and zig
| versions match. zig build-exe, zig run can be fine for small
| things, but when you want to start importing modules or do
| something more fancy, build.zig is nice to have.
| voidUpdate wrote:
| According to the extension, ZLS is optional, but according to
| some zig docs I found, its part of the extension. I may have
| misread, I'll try this stuff again sometime
| brabel wrote:
| As with all VSCode language extensions, they will try to
| download and manage ZLS for you. That's ok if it's done
| well, but they probably have some ways to go still.
|
| I just prefer using Zig on emacs with the built-in eglot
| LSP client. You just tell it where you installed ZLS (and
| it won't do magic to get it for you) and off you go. It's
| the same level of support as with VS Code. If you're not
| new to emacs, maybe consider that (otherwise emacs may be
| too much of a rabbit hole :)).
| voidUpdate wrote:
| My terminal editor of choice is nano :P
| MobiusHorizons wrote:
| It sounds like you have two editors at least, vscode and
| nano. Based on this description, I would assume you use
| nano for commit messages, config file updates, and not
| much more. If that's the case, you may want to at least
| check out what emacs or vim can do for you with some
| basic lsp integration. These would be replacements for
| vscode not nano, although once you get used to them, you
| might switch EDITOR over. Compared to the complexity of
| systems programming, vim or eMacs should be well within
| your grasp.
| jay-barronville wrote:
| > [...] I've had a lot of issues getting editor integration to
| work correctly. I've installed the VSCode extension but I don't
| seem to be getting autocomplete etc. [...]
|
| If you use ZLS [0], make sure you're always using the right
| version for the Zig version you have installed on your machine.
| In my experience, that fixes 90% of editor issues I've
| encountered using Zig (I don't use Visual Studio Code though,
| so it's possible your editor issues are related to the editor
| itself).
|
| [0]: https://github.com/zigtools/zls
| nindalf wrote:
| Honestly same. I think it has the potential to be a great
| language and I'll definitely have a look at 1.0. Right now it's
| more for the people who are fine living on the bleeding edge.
|
| Nothing wrong with that, imo. It's hard to evolve a language
| without having the ability to make breaking changes. They're
| doing the right things, generally making the right calls, and
| taking their time building instead of rushing.
| jeroenhd wrote:
| I have the same issue. It's hard to say if the tooling is
| working but incomplete, or if the tooling doesn't work for some
| reason. I can get syntax highlighting to work, but basic
| variable autocomplete doesn't, so I'm guessing the language
| server ran into some kind of issue.
|
| I really want to get started with Zig but I don't want to go
| back to the age of nano/edit.com for learning a new language.
| Zig is complex enough already.
| samatman wrote:
| For what it's worth, outside of some outstanding issues with
| comptime (which are genuinely difficult, if ultimately
| solvable), I've found autocomplete, go-to-definition, and the
| other LSP semantic tools, to work fine in vs-code.
|
| You could hop on the Discord and get some help with your
| configuration if you'd like. All things Zig are somewhat
| underdocumented currently, that could use some polish for
| sure.
| dgb23 wrote:
| > For example, the recommended way to start a project, with
| `zig init`, has a load of code that I really don't need when I
| just want a bare project to get started.
|
| I recently started a new project. zig-init provides you with a
| working build.zig file and two very minimal project files under
| /src, one of which is a hello world binary and the other is a
| hello world library.
|
| > Also I've had a lot of issues getting editor integration to
| work correctly.
|
| ZLS is not at the same level of what you would expect from a
| more mature language. For example by default it will not help
| you with anything related to comptime.
|
| I highly recommend reading this fairly recent blog post by
| Loris Cro:
|
| https://kristoff.it/blog/improving-your-zls-experience/
|
| It explains how you set up your build.zig and ZLS (a few lines
| of configuration) in order to get much more help from ZLS. It
| will then perform the equivalent of what `cargo check` (Rust)
| does.
| voidUpdate wrote:
| Really? I get a main.zig file with a hello world as well as
| some maths, and a build.zig that has stuff that I can't work
| out how to correctly get rid of. I'm not currently at that
| workstation so I can't give specifics though. I feel it would
| be easier if it was literally just a hello world print and
| the build literally just built it, rather than doing tests on
| code I already know works, because it shipped with the
| language
| dgb23 wrote:
| Yes, that's what I meant. But I think I talked passed you
| in a way.
|
| I think its fair criticism that as a beginner, you don't
| actually want to deal with build.zig or even understand it.
| You just want to write some code and run it and look at
| build.zig after you gained some familiarity with the
| language itself.
| Uptrenda wrote:
| Those function definitions really look amazingly readable. I've
| seen this done before in other languages and its usually quite
| horrible. Maybe Zig is worth learning? This is a killer feature.
| montyanderson wrote:
| i like your site! seems like zig is really taking off.
| WalterBright wrote:
| Example from the article: const win32 =
| @cImport({ @cInclude("windows.h");
| @cInclude("winuser.h"); }); pub fn main()
| !void { _ = win32.MessageBoxA(null, "world!",
| "Hello", 0); }
|
| Equivalent D: import windows, winuser;
| void main() { MessageBoxA(null, "world!", "Hello",
| 0); }
|
| In essence pared it down to the essentials. The compiler figures
| out the rest.
|
| Sometimes people ask for a special syntax for importing C files,
| but I like this simplicity so much better.
| throwawaymaths wrote:
| Some of us like explicit invocations, not being unsure if
| something comes from a .h filenor some other importing
| mechanism (what if a .h file collides with another import
| mechanism)
|
| Naked imports are also annoying. Which import did that
| MessageBoxA come from? windows? or winuser? Is it in the
| language kernel?
|
| Explicit is better than implicit. The utter pain for the code
| writer of four or five keystrokes here and there is not worth
| confounding the code reader.
| WalterBright wrote:
| Imports are found along the search path (just like .h files
| are searched for by the C preprocessor). The first one found
| it the one selected (just like the C preprocessor does).
|
| > Which import did that MessageBoxA come from?
|
| If it exists in two or more imports, the compiler will give
| an ambiguity error. To resolve the ambiguity error, qualify
| the call with the name of the import:
| windows.MessageBoxA(null, "world!", "Hello", 0);
|
| or, one can do this: import windows :
| MessageBoxA;
|
| or this: import windows, winuser;
| alias MessageBoxA = windows.MessageBoxA;
|
| You can be as explicit as you like, and don't need to worry
| about ambiguity because the compiler will issue an error for
| that. It works the same way for D imports.
| throwawaymaths wrote:
| Compiler giving a compiler error still favors the writer,
| not the reader of code. It seems like in its design in
| general D favors the writer of code with all its
| complicated bells and whistles that one must keep in mind
| as a reader. I think decades of experience has shown us
| that it is way better to favor the reader.
| WalterBright wrote:
| You can do it either way in D. It's nice to have a
| choice! I use both methods, depending on the context.
| david2ndaccount wrote:
| I wrote a blogpost showing how you could do a similar thing in D
| with ImportC.
|
| https://www.davidpriver.com/C-macro-reflection-in-D.html
___________________________________________________________________
(page generated 2024-07-30 23:00 UTC)