-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
introduce Zig Object Notation and use it for the build manifest file (build.zig.zon) #14523
Conversation
* std.zig.parse is moved to std.zig.Ast.parse * the new function has an additional parameter that requires passing Mode.zig or Mode.zon * moved parser.zig code to Parse.zig * added parseZon function next to parseRoot function
* improve error message when build manifest file is missing * update std.zig.Ast to support ZON * Compilation.AllErrors.Message: make the notes field a const slice * move build manifest parsing logic into src/Manifest.zig and add more checks, and make the checks integrate into the standard error reporting code so that reported errors look sexy closes #14290
Does that mean you could technically have structs which appear callable? I think that could be nice if used sparingly const log = struct {
pub var allow_debug: bool = false;
pub fn (comptime fmt: []const u8, args: anytype) void {
std.io.getStdOut().writer().print(fmt, args) catch unreachable;
}
pub fn debug(comptime fmt: []const u8, args: anytype) void {
if (!allow_debug) return;
std.io.getStdOut().writer().print(fmt, args) catch unreachable;
}
};
pub fn main() anyerror!void {
log("i am a callable struct", .{});
log.debug("i am also callable", .{});
log.allow_debug = true;
}
|
I don't think that's what's implied. I imagine you'd still have to use arbitrary identifier syntax, so it would have to be ' |
On #14290 there appeared to be a decent amount of support for naming the file just |
The build manifest filename sits in the root of the global namespace of a project source directory, so it must communicate the following pieces of information:
"build.zon" fails the first requirement. |
The "z" in . This is perhaps a fairly minor gripe, and I can't argue with |
"package.json" is a great example of a poorly named manifest file. JSON is a standard file format that, while it uses a subset of javascript syntax, it does not mean that the contents of the data are related to javascript. Similarly, ZON is intended to be a standard file format that any project could decide to use, and the contents of the file may not have anything to do with Zig. "package.json" could very well be the package manifest file for Ruby, Python, Rust, Zig, Go, etc., since ".json" is only the data format, and does not have anything to do with the meaning of the data. Of course we know it to be specifically for nodejs, which already has a habit of naming things poorly ("/usr/bin/node" rather than "/usr/bin/nodejs"). So, I hope you will agree now, "build.zon" fails the first requirement. As an example of an acceptable filename, consider "zig-pkg.zon". Whether to spell it out as "package" should be correlated with the related subcommand, which would probably be |
No one asked or wants my opinion on this lol but I will just say that I think And, aside, I’m excited for Zon in general I think that was a great idea. Ini felt bleh but I had nothing constructive to add there, only complaints, so I kept my mouth shut. Now that Zon was proposed and done, I think this is a really cool direction. I’m going to play around with it more generally as a config format. |
I agree with |
I would have opted for having |
Apologies, I am late to the party, but Apologies for a noob question, but is there any specific reason we have to separate const libz_dep = b.dependency("libz", .{
.target = target,
.optimize = optimize,
.url = "https://github.com/andrewrk/libz/archive/8bf2a1c61b87773131bee2086737b5f02b7c0888.tar.gz",
.hash = "12209e851f7e2c6ba2f01de3e11b1771f03e49666065320abd8414aac152bfa75fae",
}); or better yet const libz_dep = b.dependency("https://github.com/andrewrk/libz/archive/8bf2a1c61b87773131bee2086737b5f02b7c0888.tar.gz", .{
.target = target,
.optimize = optimize,
.hash = "12209e851f7e2c6ba2f01de3e11b1771f03e49666065320abd8414aac152bfa75fae",
}); or the best, hashes automatically calculated by external service providers like https://www.metalinker.org/ const libz_dep = b.dependency("https://github.com/andrewrk/libz/archive/8bf2a1c61b87773131bee2086737b5f02b7c0888.tar.gz", .{
.target = target,
.optimize = optimize,
}); |
The problem with specifying dependencies completely within the |
Also, the reason we have to specify the hash is that the package manager is completely decentralised and does not (and should not) rely on any external service, and the hash is necessary for the package manager in its current form to function without redundant fetches every single time you build. |
I agree with the problem of executing arbitrary build code, but the problem is the same will remain same whether the dependency is mentioned in build.zig.zon or build.zig. I am not a great fan of JAVA but one problem it solved for masses was the exclusion of ugly HEADER_FILES. But now it seems that ZIG is trying to bring HEADER_FILES back under the guise of ZON. ZON basically goes against the first principle of ZIG programming language
To be precise, ZON is the PREPROCESSOR zig promised to keep away.... |
You are missing the whole point here... Package Manager is decentralized, you will download the packages as peer dependency, and I am pointing to the fact that SHA256 HASH can also be downloaded, cached and verified completely through decentralization. Check the auto-update features implementation in Scoop for a clear understanding of the concept |
No, zon is not code and doesn't need to be executed. It's just a data format, like JSON.
You might have to explain this a bit more haha 😅
The hash serves two purposes:
Both of these require that the hash should be stored in the package configuration, rather than downloaded from anywhere, for different reasons:
|
Preprocessor also does not need to be executed. Check the definition and you will understand. JSON is a poor example, Javascript/ECMAScript is moving to config.js because JSON is bad. Also the Build {
.name = "libffmpeg",
.version = "5.1.2",
.dependencies = Dependency {
.libz = .{
.url = "https://github.com/andrewrk/libz/archive/8bf2a1c61b87773131bee2086737b5f02b7c0888.tar.gz",
.hash = "12209e851f7e2c6ba2f01de3e11b1771f03e49666065320abd8414aac152bfa75fae",
},
.libmp3lame = Dependency {
.url = "https://github.com/andrewrk/libmp3lame/archive/b8408fa9dc751baee2a03cd430a996920ca2c5bc.tar.gz",
.hash = "122025fb57739eb67edbbafed2b270479089ee7395cf4b0849001ab95c16a2bae0d9",
},
.libvorbis = Dependency {
.url = "https://github.com/andrewrk/libvorbis/archive/a1dc13ff76e262007eea91894dd16d74c2147619.tar.gz",
.hash = "1220d6c5bf73bee37589a086147ab8f7e855ee98becd3f2e26e58a920ca8f766105f",
},
.libogg = Dependency {
.url = "https://github.com/andrewrk/libogg/archive/9f514ae46e28589e47d25017385eb0d6ff4c7e9a.tar.gz",
.hash = "1220f96a4eaae5bad95ab9391431f125b7cc32edbd6d17397ce066d498f8fc9b63c2",
},
// This is used to compile some assembly files into object files for x86.
// Without this, ffmpeg considers the build "crippled".
.nasm = Dependency {
.url = "https://github.com/andrewrk/nasm/archive/5ef3ed029e4917d07c88f265c7b12fcfd81bd6ab.tar.gz",
.hash = "122032bc8d97d857b7c2f71252da293e4f293a4ea0d162909fb0705ba17c40ae2a87",
},
},
}
Header It's CompSci 101 not Compiler Design 301, or are they not teaching compiler design anymore? The same information is repeated, in the code and the header file. Who do you think is going to maintain those? Either you have worked on commercial C/C++ projects or you have not - no one can explain the problem of maintaining Header files. cargo.toml sure if you want to be rust, but then tell the world that ZIG cannot handle building, don't brag that ZIG is a build system as well. CARGO:RUST:::ZIG - doesn't require a deep neural network based on BoW to solve this equation. Even if you were to be cargo.toml, Cargo does not differentiate between local and global dependencies, neither should you. To make it clearer there is only one CARGO.TOML - uno, une, ein, #RustFoundation did not create another CARGO.TOML.RON to take care of external dependencies. package.json sure if you don't want to learn from history, otherwise you should look at something better maybe
LOL, haha 😅. If it could happen, it would have happened already. It is not possible and the proof is Magnet. Are you living under a rock? Let's leave security to the experts now.
Cached somehow, why do you think burdening programmer instead of a computer / build system / compiler is a better option? If the community or foundation cannot stick to its own principles, I think it is better to go back to #EvilCorporations. |
@sarvex please try to be civil, being patronizing and throwing insults around helps nobody :)
JSON is directly comparable to zon. Zon doesn't require execution because it's not a data format. This makes it easier to write tooling that deals with dependency graphs, as @mlugg mentioned earlier.
Actually, Zig struct literals can absolutely take the form
The only information that's duplicated between
I'm not entirely sure how magnet links support your position here - they include a hash directly in the link, meaning you're still putting the hash in the file.
To be fair, you're right - you don't strictly need the hashes in order to do caching effectively. However, given you do need the hashes for security reasons, it makes sense to use them for caching as well :) |
Dependency Graphs are Dependency Graphs, they do not differentiate between file:// and https:// or git+shh://. If we can agree on that then the discussion can be fruitful. And we need to also agree @silversquirl that doing things right if more important than doing easy things.
Agreed, I was not aware of that.
The only information repeated in header file is the signature, when we are talking about C / C++.
Then we need to have a better understanding of how magnets work and how they can free us from the
Yeah, so we agree that caching is different than burdening the programmer? My argument boils down to a single line We must test our underlying beliefs to see if they are really true or not As the timeless saying goes - Only a fighter falls while fighting on the battlefield. It is not a child who walks on his knees. |
@sarvex I would say that the current version of I would think based on the tasks in the project that this will evolve such that in most cases users will use the command line A crude example of what it might look like using zig pkg init my-package-name
zig pkg add "@zig/std-extra" --version 0.42
zig pkg add "@draagren/fuzzy-matcher"
zig pkg add "@user/package"
zig pkg fetch // downloads and verifies that dependencies match
zig pkg version next-minor // updates your own package version
...
zig pkg check // checks for any updates
zig pkg update "@zig/std-extra"
zig pkg remove "@user/package" |
@DraagrenKirneh I was not familiar with the perspective you are sharing now, but if it is a lock file, automatically generated by the tool,
Even with the updated perspective it is really important to understand that just because we are handling external repositories, we do not need additional files. zig pkg update "usr_pkg"
zig pkg remove "@user/package"
zig pkg add "../usr/pkg" Why should these commands be different? And why do the need a separate ZON file, why can't they make changes to build.zig directly? Or coming back to the original design - why cannot these commands be automatically invoked by build.zig? With a greenfield approach GO and DENO nailed it. the best possible mechanism for importing modules, the most simplistic model possible. When we have seen better things, Why are we regressing to dark ages? |
I think I may have not worded myself good enough in the previous post. If you read through some of the ideas / threads on the different tasks in the project you would see that there is more than just using it as a lockfile which are planned / discussed.
So that it is possible to get feedback, be enhanced, and built upon. For example like getting feedback, bugs, issues on downloading the packages themselves so this part can be improved upon.
??? what do you mean here, the terminology, or the tool, or something else?
There are a lot of pitfalls going down a edit build.zig as it can do whatever, and you would actually need to run the build itself and the code to get the real data needed, consider this mock example in a build.zig:
Never used any of those so I cannot say much about them, but again if you read through the proposals it would give you a better idea about the scope this package manager is trying to solve. |
Sure, opinions are necessary. Either we need the lockfile or we don't - it can't be one for external dependencies i.e. https:// and another for local i.e. file://
Definitely, I am unaware of these discussion. I stumbled upon this PR because mach wanted to move to new zig package manager. Point me in the right direction and I will definitely go through the discussions and contribute
Definitely feedback is crucial, but again there is nothing about ZON being self-generated and the answers I received earlier echo the same notion.
MonoRepo as a concept implemented by bazel, Nx and so on, basically...
Again, C / C++ started with HEADER_FILES to deal with list_of_dependencies_not_known_before_runtime and the rest is history. If GO and DENO can handle it so can ZIG.
It would request you to go through the examples provided in the links to have a better understanding of what if the current State of Craft. Node has |
You haven't as of yet provided any practical solutions for the problems |
@silversquirl I have provided all the information necessary to solve the problem without using To sum up
If this is hard to implement then let me know and I will make the necessary changes. |
None of those approaches work, as they require executing code to build the dependency graph. The whole point of |
Premature optimization is root cause of all evil What you are calling arbitrary code execution used to be called heuristics Zig is not the first build system trying to build a dependency graph by arbitrary code execution, it has been done by so many other tools that in 2023 an AI bot can write the code required. Bazel, Nx and TurboRepo even provide visualization tools for dependency graph. |
Even at the dumbest level the contents if I put the contents of |
If you have a suggestion for a safe, simple, fast way to do this with arbitrary code execution I'd love to hear it. |
Maybe the best way to evaluate this would be to create a real world example? We could create a script that generate a dependency graph and publish it on github in hundred repositories. This would provide a real world example taking into account all real world factors. Allowing for testing multiple approaches. I don't know how useful/realistic this would be, but many times real stress testing helped me evaluating real bottlenecks. |
@silversquirl why is it becoming very clear that you do not have any clue about Arbitrary Code Execution. Are you a developer or a security consultant? Because I am both, with three decades of experience. Why don't you do a PoC and tell the world how this imaginary ACE will work, because till now Google, Facebook, Microsoft have failed to see this flaw. I am not here to educate you, still - File does not make code anything faster, it is the slowest mechanism. Code and Data makes fetching faster. And it is the Data which makes Arbitrary Code Execution possible, and thus a file filled with additional data will make ACE possible. @andrewrk regarding your comment on #14265, if declarative programming makes so much sense why choose imperative programming at all in @kuon the dependency graphs are already made by monorepp tools such as bazel, nx, turbobuild. But none of them required two different files in two different programming paradigms and worst containing duplicate information that is hard to maintain by hands of programmers. |
|
This comment was marked as off-topic.
This comment was marked as off-topic.
I will try to stay technical, and hope for calm. My suggestion of real world testing is to try to see if the But regardless of the performance consideration, which is only important if the bottleneck is really important (we can allow a few seconds to resolve a graph, even maybe a minute, but not 15 minutes). The tooling is IMO the main argument. We want commands like |
Sorry for my unclear wording - by "arbitrary code execution" I mean "you have to run the build script". I'm not referring to any exploit, simply the fact that package-defined (ie. arbitrary) Zig code has to be run in order to build the dependency graph. |
I looked a a few of my projects, and some have quite complex |
I don't know if that would be the objective, but e.g.: {
"name": "header-lib-example",
"description": "A simple D header library (C binding to libmylib.so)",
"targetType": "sourceLibrary",
"libs": ["mylib"]
} |
Can we use this to JUST download some non-Zig dependencies too? e.g Can i for example use it to just download the |
Yes, let me file the issue for that. One moment... done: #16643 |
Note: the actual diff is much smaller; I moved parse logic from one file to another, but it is unmodified except for an additional function.
Description
This branch introduces Zig Object Notation which can be parsed using the standard library. The same function used to parse zig files is augmented to also parse zon files, using an enum to toggle between the two modes. I considered using a separate implementation to parse zon files, however, I made the decision to reuse existing logic for the following reasons:
zig fmt
for free.Next, this branch switches to
build.zig.zon
instead ofbuild.zig.ini
for the manifest file and enhances the relevant error reporting.This is the last remaining planned breaking change to the package manager, other than these two:
These will not be quite as invasive breakages, so, after this branch is merged, it starts to become more feasible for people to jump in and start using this new feature of zig.
Closes #14290.
Follow-up work to be done:
@import
.zon files #14531\x00
(null bytes) and empty string in@""
identifier syntax in the language specification #14534.
in tuples & anonymous struct literal syntax #5039