module MainFile {
public use fizz;
public use foo;
public use bar;
}
the problem is that if foo.chpl and bar.chpl are in a subfolder, it seems they cannot be found. It works by having all files in src but this could backfire for bigger projects. Is there a work-around for this?
edit: the question probably overlaps significantly with this other topic
Reading that discussion, I understand there is currently no work-around?
For the records, I know about the include submodules functionality, the problem is that that requires all subfiles to be inside a folder called like the main module (MainFile in my example above). I want to be able to name my folders freely and also possibly use multiple subfolders.
Mason packages that are libraries are expected to provide a single top-level module with the same name as the mason package. With the above structure, the code is providing 4 top-level modules (MainFile, fizz, foo, and bar). In Chapel programs, the top-level modules all share a single namespace. I know your real application does not have a module named foo, and that is a stand-in for another name. Keeping with that name, If you later want to use another library that also has a top-level module named foo, that would cause problems. However, I don't think mason checks for this and there might be cases where a mason package really does want to provide multiple top-level modules. I have not seen one yet, though.
The solution to this problem that we recommend is to use module include.
Perhaps you could use symbolic links in order to structure your files the way you like but to also provide the structure that module include needs.
Now, the above answer is mostly irrelevant if you are using mason to write an application (vs a library). If you are writing an application, you can use mason build -- -M folder/ and that will just add the -M folder/ argument to the chpl command invocation to add your folder to the module search path. Something you will notice about that command is the -- and, in Mason, that is how you can pass flags to the chpl command, rather than passing them to Mason itself. That should allow your example to build as you have described it.
In the future, we plan to look at allowing such chpl arguments to be provided in a mason .toml file, but we are not there yet.
Maybe this was an XY-problem, I guess my real question is: what is the idiomatic way to structure a bigger library in Chapel? (it's only a matter of time before Chapel gains popularity and several people start writing libraries in it )
Based on your answer, I understand the proper way is to use submodules. Is the following a legit structure?
The library has several subfunctionalities, in which case submodules are perfect (cfr. submodules in python libraries).
The module is simply too large to readably fit one file, in which case I simply want to span the module over multiple files (in my latest example, this could be SubModule1, which is scattered across file1.chpl and file2.chpl).
I'll try the above approach, meanwhile, happy to hear if you have other comments
Right, submodules are great for 1. I think we have been imagining that they will work OK for 2. as well, because you can choose how to divide the code, and then use re-export functionality to make it appear as if they were all implemented in a single file. (Where public use SubModule; is the way to re-export everything).
module MyPkg {
include module BasicUtil;
include module AdvancedUtil;
public use BasicUtil;
public use AdvancedUtil;
}
now Advancedutil also needs functions from BasicUtil, however I cannot just do use BasicUtil since mason won't be able to find it (if I had a flat structure with all source files in src/ then it would work, but that would break the one main module rule. Why cannot it find the sibling file anymore if they are submodules?).
I was able to find two work-arounds
add a use MyPkg instead of use BasicUtil in the submodule, but it feels a bit dirty, since it's breaking modularity and turning everything into "one blob".
Add a require "src/MyPkg/BasicUtil.chpl"; before use BasicUtil in AdvanceUtil.chpl.
Interestingly enough though, the second option was working for a very simple toy example (proc foo(x) {return x + 1;} defined in Basicutil and proc bar(x) {return foo(x) + 1;} , but when I tried that on my real library, it led to some where clauses to evaluate to false (previous commit using solution 1 was working).
Comments on option 1 vs option 2? Is this use of require for chapel files a misuse? (given it's documented only for c files)
I'd lean against the require for Chapel files as I'm not sure that we'll keep that working.
I think you have found some bugs but I can suggest the workaround of, in AdvancedUtil, doing use MyPkg.BasicUtil.
Here is an example that reproduces both your original issue and the workaround fixing it:
// MyPkg.chpl
module MyPkg {
include module BasicUtil;
include module AdvancedUtil;
public use BasicUtil;
public use AdvancedUtil;
}
// MyPkg/BasicUtil.chpl
writeln("in BasicUtil");
// MyPkg/AdvancedUtil.chpl
use MyPkg.BasicUtil;
// I believe this should work but it does not
//use super.BasicUtil;
// I think this should also work but it does not
//use BasicUtil;
writeln("in AdvancedUtil");
IMO the next step, other than using this workaround, is to create the issue. I can do that if you are not up for it.
Your solution of doing use MyPkg.BasicUtil is perfect! Clean and elegant (and in retrospection pretty obvious ) and indeed it works.
Happy to help with the issue by e.g. sharing my MWEs and observations, but I probably would prefer someone with stronger / more informed opinions on the matter to open it, since I wouldn't be able to argue why use super.BasicUtils or use BasicUtils should be expected to work. Do ping me though if you open the issue, happy to help debug etc.