1
$\begingroup$

After spending more than 1 hr on this, and looking at many questions, I give up as I am not able to figure a solution.

I have my current package in the standard location given by FileNameJoin[{$UserBaseDirectory, "Applications"}] which on windows is

C:\Users\Owner\AppData\Roaming\Mathematica\Applications

My package is nma, so I have in the above the standard set up of nma.m and kernel\init.m where init.m loads all the files using Get.

C:\Users\Owner\AppData\Roaming\Mathematica\Applications\nma\nma.m
C:\Users\Owner\AppData\Roaming\Mathematica\Applications\nma\A.m
C:\Users\Owner\AppData\Roaming\Mathematica\Applications\nma\B.m    

C:\Users\Owner\AppData\Roaming\Mathematica\Applications\nma\kernel\init.m

The above is all working fine. I can do

 <<nma`

From any notebook, and all the files in the package are loaded just fine.

But I do not like to keep my software on the C drive. My backup software only backups another drive. So I wanted to move C:\Users\Owner\AppData\Roaming\Mathematica\Applications\nma\ to say G:\ drive and the whole tree to say G:\mathematica_version\code\nma\. But when I did this, and made sure to open the notebook in same folder and made sure to do SetDirectory[NotebookDirectory[]] so that current directory is the above where all the files including kernel folder are, now when I do

 <<nma`

It no longer loads all the files in the package, it only loads nma.m, because I assume it does not use init.m in the kernel folder anymore, where init.m was loading all the other .m files.

It seems application_name/kernel/init.m is only used when the package lives in the standard location C:\Users\Owner\AppData\Roaming\Mathematica\Applications ? Is this true?

My question is, how to copy Applications\nma\... from C drive to any other location and have

<<nma` 

work the same as before? i.e. as if the package was in the standard location?

I tried my other things, like AppendTo[$Path,"G:\\mathematica_version\\code\\nma"] but this had no effect.

So currently after moving the package to the different location, I have to now manually do a Get on each file. This is something that init.m was doing before. i.e. I am doing this now

 SetDirectory[NotebookDirectory[]]
 Get["nma.m"]
 Get["A.m"]
 Get["B.m"]
 etc... 

for each .m file. I would prefer to have init.m do this as before if possible.

Update

I also tried the following. Changed $UserBaseDirectory to point to the location in the other disk. Removed all the Application\ folder and moved it to the new location. But this did not work. When I did

<<nma`

It did not load the package. To change $UserBaseDirectory I had to do the following

 Unprotect[$UserBaseDirectory]
 $UserBaseDirectory="new path here"
 Protect[$UserBaseDirectory]

So I copied the Application folder back to where it was. I thought may be by moving the whole Application tree and changing $UserBaseDirectory will make it work. May be I did not do it right, I looked at option inspector and did not see where $UserBaseDirectory is defined. Is it ok to change $UserBaseDirectory to new location? If so, what is the correct way to do it?

$\endgroup$
2
  • $\begingroup$ As far as I am aware, the only way to change $UserBaseDirectory is via the MATHEMATICA_USERBASE environment variable, everything else is too late in the launch process. Another approach would be to use symbolic links to have the files stored on the data drive, but still have them accessible from the usual location on the C drive. Finally: Why do you even need both an init.m and a main package file? Why not have both in one? As far as I am aware, Mathematica only loads the first of those files it finds? $\endgroup$
    – Lukas Lang
    Jan 16, 2023 at 7:32
  • $\begingroup$ @LukasLang I need init,.m because of the way the files are loaded is not the default way. I am using this method here so I need init.m for that. But for now, I load all the subpackages manually as I showed. Not a big deal. But will be nice if I can move Application tree to my data disk instead of having it on C drive. Will look at the link you gave. THanks. $\endgroup$
    – Nasser
    Jan 16, 2023 at 7:39

2 Answers 2

1
$\begingroup$

I tried my other things, like AppendTo[$Path,"G:\\mathematica_version\\code\\nma"] but this had no effect.

The location you need to add to $Path is one level higher: "G:\\mathematica_version\\code". After this, try FindFile["nma`"] to verify that it returns "G:\\mathematica_version\\code\\nma\\Kernel\\init.m".

As Victor points out in his answer, the system will look for:

  • nma/Kernel/init.m
  • nma.m

Note that it does not look for nma/nma.m. The package can either be in a single file (nma.m) or in a directory organized in a standard way (nma directory containing init.m in one of the standard locations).

$\endgroup$
1
$\begingroup$

Documentation for Get (Wolfram Desktop 13.2 on macOS) states

enter image description here

which I always interpreted that the files are searched in that order and that the first file found stops the search. If that interpretation is right, then the new behavior you are observing is correct.

It's unclear why then you would have things working under the old setup - I would put my money on some undocumented special handling of system directories due to some legacy reasons.

Update. Here is a little experiment I did (I have ~/Documents/packages/ added to my $Path) which proves my hypothesis above:

createMX[path_, num_] := Block[{myPrint},
  If[num < $minNum, Return[]];
  myPrint[] := Print[num];
  DumpSave[path, myPrint]]

createWL[path_, num_] := Block[{},
  If[num < $minNum, Return[]];
  WriteString[path, "myPrint[] := Print[" <> ToString@num <> "]"];
  Close[path]]

createContext[dir_, context_, min_ : 1] := 
 Block[{prefix = dir <> context, $minNum = min},
  createMX[prefix <> ".mx", 1];
  createWL[prefix <> ".wl", 2];
  CreateDirectory[prefix <> "/"];
  CreateDirectory[prefix <> "/Kernel/"];
  createWL[prefix <> "/Kernel/init.wl", 3];
  createWL[prefix <> "/init.wl", 4];
  createWL[prefix <> ".m", 5];
  createWL[prefix <> "/Kernel/init.m", 6];
  createWL[prefix <> "/init.m", 7];
  ]

createContext["~/Documents/packages/", "mytest"]

<< mytest`

myPrint[] (* 1 *)

createContext["~/Documents/packages/", "mytest1", 3]

<< mytest1`

myPrint[] (* 3 *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.