I am currently creating a library, or rather a base module for other addons to build on. It is implemented as a library though.
Now this library uses a number of other libraries, like Ace and LibStub.
I would like it to conform to the default behavior of being able to install standalone (for no libs users) and be embeddable by addons that use it.
I have structured it in a way that toc, pkgmeta are at the root, and then the actual library is in a subfolder. Consumers of the library will then reference this subfolder to embed.
Now the problem is that when embedding, the libs folder (which should also go under the aforementioned subfolder) is not retrieved. This is fairly logical since it doesn't exist but is created by the packager as defined in the pkgmeta.
So what is the best practice to solve this?
1. I could hard embed the libraries used. This would break nolib conformity and I'd rather not do that. Plus its a pain to ensure they are the latest version.
2. I can make the libraries used required dependencies and make it the responsibility of the consumer of my library to ensure that the required libraries are loaded before mine. And then completely removed them from my addon pgkmeta and all.
Or is there a third option that will make it all work as intended, i.e. having the libraries retrieved dynamically also when embedding?
1) There is no "Ace" library. There is the Ace3 family of libraries, each of which is standalone. Which one are you using, and how are you using it? Unless your library is an AceGUI widget, or an AceConfig interface, you should probably rewrite it without using the AceWhatever-3.0 library.
2) If you use Library X, which requires Library Y, then your addon embeds both Library X and Library Y by listing them as externals in your pkgmeta file. Your TOC file calls Library Y first and Library X second. You list both addons as OptionalDependencies in your TOC file.
Most users download the standard ZIP with libraries embedded, and need not be aware that any libraries are used, or even what a library is. The packager automatically puts the right libraries in the right place in your addon folder when it makes the ZIP.
Users who choose the -nolib ZIP without libraries are probably using the Curse Client, which will automatically download the libraries separately based on the externals specified in your pkgmeta file.
Users who are manually managing standalone libraries will look at your TOC file, see which libraries you are calling, and manually download those libraries.
Embeddable libraries should never be listed as required dependencies.
I'd suggest looking at existing addons that embed LibStub-based libraries if you need more specific examples of what you need to add in your pkgmeta and TOC files. BigWigs, Omen, and Recount are some very popular addons on WowAce that are correctly embedding libraries and can be used as examples.
I will bet that Phanx might trample me like a horde of Horde, but you could look at LibGuildBankComm-1.0, which embeds AceComm-3.0 (which itself embeds ChatThrottleLib), AceSerializer-3.0, LibCompress, LibStub, and CallbackHandler-1.0.
@Phanx thanks but it seems you have misunderstood my question.
I am well aware that Ace is not the name of a library, however which library I am using is irrelevant to my question, but since you ask, I am using AceGUI and AceLocale.
I am not asking how to write toc or pkgmeta files, I am asking how a library that is using other libraries ensure that its external dependency requirements are met when another Addon developer embeds it, i.e. has it as an external in his pgkmeta.
Of the 2 listed options I wrote in my initial post, neither seems very smart, which is why I put it to the forum if there is a third option I am missing.
What you write in your bullet 2, suggests my option 2, which I agree is the lesser of two evils.
@Myrrodin thanks I will have a look at that, that is exactly what I was getting at.
Ok, so I had a look at your library Myrrodin. And clearly you are doing option 2, leaving it to the consumer to ensure that all libraries required are loaded before yours.
Looking at AceComm-3.0 though it hard embeds ChatThrottleLib, so there we have my option 1.
So it seems my options are limited to those two, in which case I'l go for option 2.
Now if I could add behavior to the packager, I would add an option to the externals part, resolveExternals, which if set would cause the packager to resolve the externals of externals so to speak. That way consumers of a library would not have to know and satisfy the entire tree of dependencies; just the ones they use directly, the rest would be auto resolved.
I actually tried adding a second pgkmeta to the subfolder references by other addons in their externals. But no such luck.
In LGBC's case, I specifically opted NOT to have LibStub, CBH, AS3, LC, and AC3 as "no-lib", and while I did not hard embed any of them, I turned off the enabling of "no-lib" in LGBC's pkgmeta.
That way, end users who strip libs will only see one library (LGBC) instead of six. Well, five, as the Ace libs strip out as "Ace3" which contains the individual Ace libraries. Anyway, long story short, yes, I went with option 2.
Note that AceComm-3.0 MUST hard embed ChatThrottleLib due to its design. CTL is kind of not useful by and in of itself as a standalone library.
Yeah I know I only need one pkgmeta, I just tried adding a second in the hope the packager would honor it during exernals resolution.
I believe my question has been answered, only the two options I listed are possible.
What I have done is write Xinhuan with my suggested improvement to the packager.
I am well aware that Ace is not the name of a library, however which library I am using is irrelevant to my question, but since you ask, I am using AceGUI and AceLocale.
Far from being irrelevant, which libraries you're using is central to your question. Some libraries are intended to be used by other libraries; others are not.
You should not use AceLocale in a library. Just hardcode the translations. (I'd argue that nobody should ever use AceLocale for anything because it can be replaced with 5 lines of code, but that's another can of worms entirely.)
You should also not be using AceGUI in a library. If your addon is presenting a GUI to the user, it is not a library, or you are failing to properly separate the library's features from your addon's features.
Far from being irrelevant, which libraries you're using is central to your question. Some libraries are intended to be used by other libraries; others are not.
You should not use AceLocale in a library. Just hardcode the translations. (I'd argue that nobody should ever use AceLocale for anything because it can be replaced with 5 lines of code, but that's another can of worms entirely.)
You should also not be using AceGUI in a library. If your addon is presenting a GUI to the user, it is not a library, or you are failing to properly separate the library's features from your addon's features.
Well I did clarify in my original post, that this isn't actually a library, it's a base module, an abstract class if you will.
It is however also not a standalone addon, as it does nothing on its own. It provides plumbing and the default UI elements for the very specific addon category for which it is a base. clcInfo class module plugins to be specific.
This is my second addon, and I am still learning the ropes. The use of AceLocale seemed like an obvious choice since it facilitates localization and it is easy for translators to provide translations through the curseforge interface.
Could you provide me with the name of the proper person to contact regarding the packager?
Officially, all packager suggestions should be posted in the CurseForge ticket tracker.
Realistically, Curse does not have anyone monitoring the ticket tracker, the packager is given a band-aid when it breaks but is otherwise ignored, and there's no reliable way to get anyone at Curse to actually listen to anything you say. I generally envision Curse ticket handling as going something like this:
Once every 6 weeks, the employees draw straws. Whoever draws the short straw is required to change the status on 3 randomly chosen tickets, and post a comment on 1 randomly chosen ticket. All other tickets are ignored.
I have had several Curse employees/volunteers promise me that they're just about to start rewriting this or fixing that or improving something, but then years pass and nothing changes, so I wouldn't get your hopes up about any suggestions actually being implemented. :(
... this isn't actually a library, it's a base module, an abstract class if you will. ... clcInfo class module plugins to be specific.
Wouldn't that put it in the same category as clcInfo itself, or kgPanels and (arguably) things like Bazooka or Titan Panel? eg. It's an addon that provides a UI, and the user populates the UI by installing plugins (or directly inputting scripts).
As with those addons, you'd embed the used libraries in your addon like any other addon, and then users install your addon + whatever plugins they want.
The use of AceLocale seemed like an obvious choice since ... it is easy for translators to provide translations through the curseforge interface.
AceLocale and the CurseForge localization UI are completely independent. I use the CurseForge localization UI, but instead of AceLocale, I use this:
local L = setmetatable({}, { __index = function(t, k)
local v = tostring(k)
t[k] = v
return v
end })
if GetLocale() == "esMX" then
L["Hello world!"] = "Hola mundo!"
end
print(L["Hello world!"])
If you're using the CurseForge packager, you can even use the translation auto-export substitution commands to copy the current translations from the translation UI on the website to the appropriate file in your ZIP download. See Grid (link in my signature) for an example of an addon using the translation web UI and packager, but not using AceLocale.
Wouldn't that put it in the same category as clcInfo itself, or kgPanels...
Well kinda, but its more of an in between as I see it. Those of the addons you mention that I know, work as hosts for plugins.
My module does absolutely nothing on its own, what it does is inject the class modules that use it with the plumbing needed to communicate with clcInfo, and common configuration pages to edit settings. In short it provides all the non class related stuff so that the author can focus on the class specific stuff.
So why don't I ask the author of clcInfo to merge this into clcInfo, which is where it belongs. Well I still have 2 month old tickets and private messages with no response so...
AceLocale and the CurseForge localization UI are completely independent.
Yeah I can see that now. And I can also see that making my own implementation would be just as easy.
Of course in order to share translations between multiple files, I would need to either expose it through LibStub or the addon table passed in at load or something similar.
So thanks for your answers, I appreciate you taking the time.
Of course in order to share translations between multiple files, I would need to either expose it through LibStub or the addon table passed in at load or something similar.
LibStub is not an appropriate method for sharing data between files in an addon. Either use the addon's private table (that's exactly the kind of thing it was designed for) or the addon's global object if it has one (which is what Grid does for translations).
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
I am currently creating a library, or rather a base module for other addons to build on. It is implemented as a library though.
Now this library uses a number of other libraries, like Ace and LibStub.
I would like it to conform to the default behavior of being able to install standalone (for no libs users) and be embeddable by addons that use it.
I have structured it in a way that toc, pkgmeta are at the root, and then the actual library is in a subfolder. Consumers of the library will then reference this subfolder to embed.
Now the problem is that when embedding, the libs folder (which should also go under the aforementioned subfolder) is not retrieved. This is fairly logical since it doesn't exist but is created by the packager as defined in the pkgmeta.
So what is the best practice to solve this?
1. I could hard embed the libraries used. This would break nolib conformity and I'd rather not do that. Plus its a pain to ensure they are the latest version.
2. I can make the libraries used required dependencies and make it the responsibility of the consumer of my library to ensure that the required libraries are loaded before mine. And then completely removed them from my addon pgkmeta and all.
Or is there a third option that will make it all work as intended, i.e. having the libraries retrieved dynamically also when embedding?
2) If you use Library X, which requires Library Y, then your addon embeds both Library X and Library Y by listing them as externals in your pkgmeta file. Your TOC file calls Library Y first and Library X second. You list both addons as OptionalDependencies in your TOC file.
Most users download the standard ZIP with libraries embedded, and need not be aware that any libraries are used, or even what a library is. The packager automatically puts the right libraries in the right place in your addon folder when it makes the ZIP.
Users who choose the -nolib ZIP without libraries are probably using the Curse Client, which will automatically download the libraries separately based on the externals specified in your pkgmeta file.
Users who are manually managing standalone libraries will look at your TOC file, see which libraries you are calling, and manually download those libraries.
Embeddable libraries should never be listed as required dependencies.
I'd suggest looking at existing addons that embed LibStub-based libraries if you need more specific examples of what you need to add in your pkgmeta and TOC files. BigWigs, Omen, and Recount are some very popular addons on WowAce that are correctly embedding libraries and can be used as examples.
I am well aware that Ace is not the name of a library, however which library I am using is irrelevant to my question, but since you ask, I am using AceGUI and AceLocale.
I am not asking how to write toc or pkgmeta files, I am asking how a library that is using other libraries ensure that its external dependency requirements are met when another Addon developer embeds it, i.e. has it as an external in his pgkmeta.
Of the 2 listed options I wrote in my initial post, neither seems very smart, which is why I put it to the forum if there is a third option I am missing.
What you write in your bullet 2, suggests my option 2, which I agree is the lesser of two evils.
@Myrrodin thanks I will have a look at that, that is exactly what I was getting at.
Looking at AceComm-3.0 though it hard embeds ChatThrottleLib, so there we have my option 1.
So it seems my options are limited to those two, in which case I'l go for option 2.
Now if I could add behavior to the packager, I would add an option to the externals part, resolveExternals, which if set would cause the packager to resolve the externals of externals so to speak. That way consumers of a library would not have to know and satisfy the entire tree of dependencies; just the ones they use directly, the rest would be auto resolved.
I actually tried adding a second pgkmeta to the subfolder references by other addons in their externals. But no such luck.
That way, end users who strip libs will only see one library (LGBC) instead of six. Well, five, as the Ace libs strip out as "Ace3" which contains the individual Ace libraries. Anyway, long story short, yes, I went with option 2.
Note that AceComm-3.0 MUST hard embed ChatThrottleLib due to its design. CTL is kind of not useful by and in of itself as a standalone library.
Please post your TOC and pgkmeta using either the code or php tags. It may help to see what you are doing in order to answer questions.
I believe my question has been answered, only the two options I listed are possible.
What I have done is write Xinhuan with my suggested improvement to the packager.
Far from being irrelevant, which libraries you're using is central to your question. Some libraries are intended to be used by other libraries; others are not.
You should not use AceLocale in a library. Just hardcode the translations. (I'd argue that nobody should ever use AceLocale for anything because it can be replaced with 5 lines of code, but that's another can of worms entirely.)
You should also not be using AceGUI in a library. If your addon is presenting a GUI to the user, it is not a library, or you are failing to properly separate the library's features from your addon's features.
Huh? What? Xinhuan doesn't even work for Curse...
Ok, I just saw him listed as author of a fair share of posts regarding the packager.
Could you provide me with the name of the proper person to contact regarding the packager?
Well I did clarify in my original post, that this isn't actually a library, it's a base module, an abstract class if you will.
It is however also not a standalone addon, as it does nothing on its own. It provides plumbing and the default UI elements for the very specific addon category for which it is a base. clcInfo class module plugins to be specific.
This is my second addon, and I am still learning the ropes. The use of AceLocale seemed like an obvious choice since it facilitates localization and it is easy for translators to provide translations through the curseforge interface.
Officially, all packager suggestions should be posted in the CurseForge ticket tracker.
Realistically, Curse does not have anyone monitoring the ticket tracker, the packager is given a band-aid when it breaks but is otherwise ignored, and there's no reliable way to get anyone at Curse to actually listen to anything you say. I generally envision Curse ticket handling as going something like this:
Once every 6 weeks, the employees draw straws. Whoever draws the short straw is required to change the status on 3 randomly chosen tickets, and post a comment on 1 randomly chosen ticket. All other tickets are ignored.
I have had several Curse employees/volunteers promise me that they're just about to start rewriting this or fixing that or improving something, but then years pass and nothing changes, so I wouldn't get your hopes up about any suggestions actually being implemented. :(
Wouldn't that put it in the same category as clcInfo itself, or kgPanels and (arguably) things like Bazooka or Titan Panel? eg. It's an addon that provides a UI, and the user populates the UI by installing plugins (or directly inputting scripts).
As with those addons, you'd embed the used libraries in your addon like any other addon, and then users install your addon + whatever plugins they want.
AceLocale and the CurseForge localization UI are completely independent. I use the CurseForge localization UI, but instead of AceLocale, I use this:
If you're using the CurseForge packager, you can even use the translation auto-export substitution commands to copy the current translations from the translation UI on the website to the appropriate file in your ZIP download. See Grid (link in my signature) for an example of an addon using the translation web UI and packager, but not using AceLocale.
Ok, that sucks. I'll try posting it anyway and see what happens. Thanks for pointing me in the right direction.
Well kinda, but its more of an in between as I see it. Those of the addons you mention that I know, work as hosts for plugins.
My module does absolutely nothing on its own, what it does is inject the class modules that use it with the plumbing needed to communicate with clcInfo, and common configuration pages to edit settings. In short it provides all the non class related stuff so that the author can focus on the class specific stuff.
So why don't I ask the author of clcInfo to merge this into clcInfo, which is where it belongs. Well I still have 2 month old tickets and private messages with no response so...
Yeah I can see that now. And I can also see that making my own implementation would be just as easy.
Of course in order to share translations between multiple files, I would need to either expose it through LibStub or the addon table passed in at load or something similar.
So thanks for your answers, I appreciate you taking the time.
LibStub is not an appropriate method for sharing data between files in an addon. Either use the addon's private table (that's exactly the kind of thing it was designed for) or the addon's global object if it has one (which is what Grid does for translations).