A package manager for making Quest il2cpp mods and libraries. Commonly acronymized as QPM
or qpm
NOTE THAT THE CURRENT IMPLEMENTATION OF QPM IS NO LONGER RECOMMENDED FOR WIDESPREAD USE! CONSIDER USING CLI qpm INSTEAD!
This repository will be archived soon and for all intents and purposes should be considered deprecated!
package
: An application with a single configuration. Can contain dependencies and has some metadata. Must have an id and a version (which must be SemVer).dependency
: A dependency to another package. Must have an id and a version range (SemVer range).sharedDir
: A folder that is exposed to other packagesexternDir
: A folder that is used for installing dependencies
Note: You can use qpm
, qpm -?
, qpm --help
, or qpm -h
to view a list of commands.
qpm package create "PACKAGE ID" "PACKAGE VERSION"
Creates a package with id: PACKAGE ID
and version: PACKAGE VERSION
(which must be valid SemVer).
This will create a qpm.json
folder in your current directory. This is your package configuration file and holds your package
.
This will also perform some modifications to your .vscode/c_cpp_properties.json
, bmbfmod.json
, and Android.mk
files, assuming they exist.
A common use case with qpm
is to add a dependency to a package.
You must first have a valid qpm.json
file within your current working directory, then you may call:
qpm dependency add "ID" -v "VERSION RANGE"
Which creates a dependency with id: ID
and version range: VERSION RANGE
. If -v
is not specified, version range defaults to *
(latest available version).
NOTE: YOU SHOULD ALMOST NEVER USE A *
VERSION RANGE! INSTEAD PREFER PROPERLY CONSTRAINED VERSION RANGES!
This is primarily a command used to ensure the package's collected dependencies match what you expect.
qpm collect
Should print out a listing of dependencies that it resolved. This command does not modify your package at all.
This is primarily a command used to ensure the package's collected dependencies are collapsible into something you expect.
qpm collapse
Should print out a listing of dependencies similar to Collect Dependencies, but with identical IDs combined.
After adding one or more dependencies
, you must perform a restore
to properly obtain them. Dependencies that are added to your package
must be resolved in order to ensure a proper build.
Dependencies are resolved using an external domain, qpackages.com
. For more information on how to interface with this package index, see the publishing section.
qpm restore
Which restores all dependencies listed in your package from the package index.
Restore follows the following process:
- Collects all dependencies
- Collapses these dependencies
- Iterates over the collected dependencies, obtaining a .so (if needed) for each one.
- Iterates over the collapsed dependencies, obtaining header information (if needed) for each one.
- Places all restored dependencies into
qpm.shared.json
(which is used for publishing)
During steps 3 and 4, QPM will modify your Android.mk
, if it exists, backing it up to Android.mk.backup
first.
At this point, you should be able to build!
There are several steps required in order to ensure your package is fit to be published on qpackages.com
.
Firstly, you must perform a qpm restore
(see Restoring Dependencies)
After, you must ensure you either have the headersOnly
additional property set to true, or you specify soLink
and/or debugSoLink
.
Then, the url must be set to either a github repository (ex: https://github.com/sc2ad/QuestPackageManager
) or will be interpretted as a direct download.
The download specified by this link MUST have a qpm.json
file that matches the version specified in your qpm.shared.json
that you plan on publishing.
YOU MUST TELL Sc2ad#8836
THAT YOU WISH TO HAVE A PUBLISH KEY AND GIVE HIM THE INFORMATION HE DESIRES! When he acknowledges, you are safe to:
qpm publish "your publish key here"
Note that you should NOT expose this publish key to ANYONE! It should be a secret in your CI runs and it will not be exposed by qpm-rust
or equivalent tools.
However, due to the nature of QPM, it is possible to publish invalid packages to QPM, which will cause people trouble.
For this reason, please message Sc2ad#8836
(you have to do this anyways) before publishing a package to QPM.
qpm package edit-extra
Can be used to add extra data to the additionalData
property, without manual JSON edits to qpm.json
and qpm.shared.json
.
qpm properties-list
Can be used to list all supported properties in additionalData
, as well as what types they are supported in.
A full list will be available on the wiki, once I get around to making it.
Full documentation for each command will be fully available on the wiki (once I get around to making it).
A subset of this information can be found by doing qpm --help
.
qpm.shared.json
, Android.mk.backup
, and extern
should never be added to a git project!
You should explicitly add:
qpm.shared.json
extern/
*.backup
to your .gitignore
.
As easy as:
qpm dependency add "<DEPENDENCY ID>" -v "<NEW DEPENDENCY VERSION>"
followed by:
qpm restore
QPM caches all restored dependencies to: <QPM WORKING DIRECTORY>/QPM_Temp/
You can forcibly clear the QPM cache by calling:
qpm cache clear
QPM was built with Beat Saber Quest development in mind. This does not mean it does not work on other games, or for other platforms, but it makes Beat Saber development very easy.
In order to get started, it is recommended you have a VSCode project open, with existing .vscode/c_cpp_properties.json
, ./Android.mk
, and ./bmbfmod.json
files.
NOTE: Using the bsqm template may cause issues, since you will need to delete your extern
folder and your .gitmodules
file before continuing!
Then, you should start by creating your QPM package. This can be done by calling:
qpm package create <YOUR MOD ID> <YOUR VERSION>
After this, you should add a dependency to beatsaber-hook.
It is good practice to specify an encompassing version range for your dependencies, so ^x.y.z
where x.y.z
is the latest beatsaber-hook
version.
This can be found by checking the latest published package by visiting this link: https://qpackages.com/beatsaber-hook/.
Once you know the version range you would like, call:
qpm dependency add "beatsaber-hook" -v "<VERSION RANGE>"
In most cases, this would be all we need to do before calling a qpm restore
and building our mod.
SADLY, beatsaber-hook
has an issue which requires us to take one additional step. We need to edit qpm.json
and edit the dependency from:
"dependencies": [
{
"id": "beatsaber-hook",
"versionRange": "<VERSION RANGE>",
"additionalData": {}
}
]
to:
"dependencies": [
{
"id": "beatsaber-hook",
"versionRange": "<VERSION RANGE>",
"additionalData": {
"extraFiles": [
"src/inline-hook"
]
}
}
]
NOW we can perform a:
qpm restore
Finally, we just need to add a few lines to our Android.mk
and we will be all set!
For your main module's LOCAL_CFLAGS
or LOCAL_CPP_FLAGS
, add the following flag: -isystem"./extern/libil2cpp/il2cpp/libil2cpp"
. This adds libil2cpp
from your extern
folder.
For the beatsaber-hook_x_y_z
module's LOCAL_EXPORT_C_FLAGS
, add the following flags: -DNEED_UNSAFE_CSHARP -DUNITY_2019
Add to your main module the following (assuming you have wildcard
defined):
LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook,*.cpp)
LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook,*.c)
For intellisense, add ${workspaceFolder}/extern/libil2cpp/il2cpp/libil2cpp
to your .vscode/c_cpp_properties.json
's includePath
.
Now you should be all set to build! (You won't need to make these modifications the next time you perform a qpm restore
)
Coming soon, QPM will allow for plugins to allow for modifications of additional files, or perform additional actions for all commands. QPM will also allow plugins to add commands as well. Literally not for a long time though.
DM Sc2ad#8836
on Discord or something, idk