-
Notifications
You must be signed in to change notification settings - Fork 499
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
Add ability to include other justfiles #237
Comments
Would it be possible to just have everything in one file, and rename the recipes? For example, I know that's a little bit annoying, but this feature would add a bit of complexity to the parser, lexer, and error messages, since they would have to be aware of multiple files. If a lot of users wanted it though, I wouldn't be opposed to adding it. |
I've considered several alternatives so far. All are workable, but not as clean as including files. Single file with namespaced targets. -- e.g.
|
I fully understand not wanting to complicate the code to solve what may well be a rare corner case. For now, I'll either use one of the previously mentioned options, or just fall back to Makefiles if I really need file inclusion. I appreciate the work you have and continue to put into this tool. It's an amazing utility that I've wanted for a while. How complicated is it to get started in rust? Working on a parser/lexer sounds like fun, but I don't know rust nor know how hard it is to get started using it. |
Rust is a bit hard to get started with. I definitely spent a week or two trying to figure out owned vs. borrowed, and then probably another week or two on lifetimes and appeasing the borrow checker. Also, there are some idioms to learn around error handling. Overall though, I think it's really nice! Also, if you do decide to pick up rust, definitely check out the rust gitter and IRC channels. They are chock full of nice, smart, helpful, beginner-friendly people. I think for now I'd like to keep this issue open, and also encourage others to comment if it's something they want or think they would use. Also, thank you very much for the kind words! |
Definitely an important feature, especially within monorepos where each microservice has its dedicated Just/Makefile but some things are shared. Another thing that directly comes to my mind is splitting of config and recipes. |
I would like to see this feature added. Regarding includes complexity with the lexer, etc. I'm wondering if it would be easier to simply build a temporary concatenated version of the main file and it's imports as a 1st phase prior to parsing, lexing, etc.? I've no idea if that would or could be done easily. I've not reviewed the code and played very little with Rust so far. Just throwing it out there. BTW, finally tried implementing Just and love it! Seems to be exactly what I've been looking for over the last year or so. |
The problem with concatenating is that one cannot report errors with precise location anymore. This would be very frustrating for the user. |
@runeimp So glad you like it! Also, I think that I would want to make it clear where things were coming from, something like: import foo
bar: foo.baz
echo {{foo.SOME_VARIABLE}} Instead of putting them all in the same scope/namespace. |
Should Variables that were |
Personally, I think having include act as a copy-paste as suggested by @runeimp is good enough. This is my understanding of how includes work in Makefiles already. As for debugging, I feel having the To put it another way, I'd rather have a copy-paste style include than no include at all. |
@casey Wouldn't having to namespace imported variables break my original use case? The purpose of imports is so multiple top level justfiles can change configuration variables as needed and the imported justfile can remain unchanged. The collision of variables is intentional.
The |
I personally would never solve the issue as you describe it in that way. I would use an environment variable that defines the, well, environment. This is currently not possible with just but could easily be supported. Make has it via That being said, I see how it could break some things if you have a common bootstrap Justfile were you define reusable options and targets for others to be included. |
@cledoux Ah, yeah, it wouldn't work in that case. This feature is going to have to be pretty carefully designed up front. I think I'll need to be able to enumerate all possible use-cases, and then figure out how the feature can support all of them. It seems like there are two use-cases being discussed in this thread, one being sharing code between different justfiles in the same directory, doing essentially configured versions of the same thing, and another being sharing configuration between different subdirectories of a mono repo. I think for the former, I would prefer to have some way to mark options as not coming from the current file:
|
@Fleshgrinder I may not have been clear. In my case, both commands are run from the same computer, so environment variables aren't really an option because I need the variable to hold different things at different times all on the same computer. If you have a better way to solve my use case, I'm all ears. I'm always eager to learn. 😃 |
Another way would be to allow different ways of inclusion, e.g. @cledoux working with environment variables is actually very powerful, especially if you need to ad-hoc change things. You would basically define them while calling just: $ just foo # this uses the defaults
$ ENV=stage just foo
$ ENV=prod just foo You could also define aliases for these in your just-stage() { ENV=stage just "$@"; }
just-prod() { ENV=prod just "$@"; } See also #245 |
@Fleshgrinder If you have to define shortcuts in another file, to use with Environment variables are always there, of course, but I think that variables defined within just have important advantages, for example being cross platform (windows environment variables are case-insensitive), getting compile-time errors when they aren't defined, being utf8, and not polluting the downstream environment needlessly. |
I disagree, adding or removing functionality based on the environment is typical in task runners and build systems. Environment variables are the typical choice for that, especially because of CI systems. Make also has special functionality to solve the previously mentioned things: build: export ENV ?= dev
build:
# do something
build-staging: export ENV := stage
build-staging: build
build-prod: export ENV := prod
build-prod: build This is one of the reasons why I ask for conditional assignment in #245. 😉 |
I have no idea how complicated it would be to implement, but what about something like the way python handles imports? An Then again, that might be overcomplicating everything. @Fleshgrinder There are multiple configurations that need changing when targeting different environments and the contents of these options are too long to type out each time I run a command. In order to use environment variables in the manner you suggest (or least how I understand you to have suggested them), I would need to do the following:
|
I like the What you would need in such cases would be a conditional include, too keep things nice and tidy. Something make also does not offer. This is actually one of the reasons why tools like autoconf were created. foo: export ENV ?= dev
foo:
import {{ENV}}.just
# command
foo-stage: export ENV = stage
foo-stage: foo
foo-prod: export ENV = prod
foo-prod: foo This does not work in make, but would be the best thing. |
For the conditional environment example, I do one of 2 approaches:
The second works better if I do have a use-case in mind where I want to be in different directories and usually do the same thing and be able to share those tasks but customize some tasks. I think for now I can accomplish this by having a shared justfile invoke a second custom just file:
I think this is a decent solution. However, there are two problems:
The second is where things can easily go awry. If I default to This can be solved by source inclusion, i.e. To summarize, I think this problem can be solved without adding import support to just, but instead with delegation, but we run into safety issues. Having a function similar to |
Another use case is sharing common justfile commands between repositories. There's a common set of commands for ci steps (build/test/deploy) that is great to live in the root of a repository, but then each repository also has commands specific to that repo. Without the ability to import justfiles, you cannot easily share sets of common tasks. If you have a separate justfile, then it needs a different name, which breaks some other functionality (just doesn't know the name of the running justfile, it assumes it is |
In the case of environment variables Just now automatically loads |
It doesn't really change the use case I'm interested in: sharing modular justfiles that can be integrated into the root justfile. |
I just posted a little update on where things stand with modules, which I think is the feature which will eventually enable the use cases mentioned in this thread. |
What's the 2021 take on this? It seems like the discussions have stranded for both this and #271 😕 .
But it ain't that pretty and also more prone to breaking than an official solution. Naturally no variable sharing either. If anyone knows an alternative to just that isn't primarily a build tool, please share! |
The 2021 take is, sadly, that things are still where they were in 2017. I started working on inline modules, thinking it might be easier than doing import statements, but it wasn't, so I abandoned the attempt. I want Just to support this, but I don't personally have any justfiles that are large enough to want to break up into modules, so I don't have a personal use-case that would motivate me to do this. So for now, it's in limbo until I somehow find the motivation or someone else picks it up. |
Alright, thanks for the update at least! 🙂 |
I'm still wondering if concatenation of files is a simple first option. I know @Fleshgrinder said it would be imprecise for errors but isn't that exactly why source map files are generated by JavaScript code minifiers such as Uglify? I'm not saying it would easy. But I think it probably wouldn't be too bad to implement compared to other options. Here are some resources to consider. |
I created an experiment https://github.com/MadBomber/experiments/tree/master/just_playing Dewayne |
As an intermediate solution, why not: execute_myreceipe_from_other_justfile:
just --justfile /my/path/justfile myrecipe myarguments This doesn't expose the recipes to |
Concatenation of files before full parsing, perhaps via an |
@ceejbot You should check out It's a justfile preprocessor that does what you want. I'm hesitant to include |
I can't see it directly mentioned here, but there's an alternative to including other files: https://github.com/casey/just#invoking-justfiles-in-other-directories Yes, this alternative may not be perfect for every case, but may be an acceptable solution for most people looking for the include feature. |
Using the new
PS I'd love love to have a |
Would it be possible to add file inclusion to Justfiles?
A semi-common pattern I have with makefiles is to use separate makefiles for different environments with a common Makefile included between them.
A trimmed down example I'm currently using is below. There are three files:
If you have a better suggestion for solving my use case that doesn't include multiple files, I'm all ears. I'm always happy to learn. 😃
The text was updated successfully, but these errors were encountered: