cargo-nx
is a simple build command for projects based on this organization's libraries and tools, to avoid having to mess with makefiles, scripts or having several copies of the same linker/target files for every single project, while also including support for generating various formats after projects are compiled.
Assuming you have Rust and cargo
installed, it's just a matter of two steps:
-
If not already installed, install
rust-src
:rustup component add rust-src
-
Install
cargo-nx
:cargo install cargo-nx --git https://github.com/aarch64-switch-rs/cargo-nx
The program can be executed as cargo-nx
or simply as a cargo subcommand, cargo nx
, and it provides the following main subcommands:
This subcommand is quite similar to the usual cargo new
subcommand.
Base format: cargo nx new <path> [<params/flags>]
Available parameters/flags
-
--name
: Specify the package name (default is the input path's directory name) -
--edition
: Specify the package edition (available editions: [2015, 2018, 2021], default is 2021) -
--type <package type>
: Specify the package type to create.lib
,nro
, andnsp
are available, withnro
being the default.
This subcommand is quite similar to the normal cargo build
subcommand.
Base format: cargo nx build [<params/flags>]
Available parameters/flags:
-
-r
,--release
: Builds on release profile, same as the normalcargo build --release
option. -
-p <path>
,--path=<path>
: Specifies a path with a crate to build (containingCargo.toml
, etc.), since the current directory is used by default otherwise. -
-t <triple>
,--target=<triple>
: Specifies the target triple (which can be a target JSON like with regularcargo build
); "aarch64-nintendo-switch-freestanding" (official tier 3 target) is used by default. -
-v
,--verbose
: Displays extra information during the build process.
Build format fields used for building must be placed placed inside [package.metadata.nx.<format>]
in Cargo.toml
. These fields vary depending on the project's format.
The program itself detects the target format when parsing Cargo.toml
. Note that multiple formats at the same time are not currently supported.
Projects without specific build format fields, like libraries, can also be compiled. This can be useful to later generate custom executables instead of being generated by this subcommand.
Projects which generate homebrew NRO binaries don't have any mandatory fields, but only optional ones.
- Example:
[package]
name = "Project"
version = "0.1.0"
authors = ["XorTroll"]
edition = "2021"
[package.metadata.nx.nro]
romfs = "romfs_dir"
icon = "icon.jpg"
nacp = { default_name = "Sample project", default_author = "XorTroll", version = "0.1 beta" }
Note: the
romfs
andicon
fields must point to items located relative to the project's directory
The fields present on the nacp
object, all of them optional, are the following:
Field | Value | Description | Default value |
---|---|---|---|
default_name | String (max size 0x200) | Default title name | Unknown application |
default_author | String (max size 0x100) | Default application author | Unknown author |
version | String (max size 0x10) | Application version | |
application_id | Hex-String u64 | Application ID | 0000000000000000 |
add_on_content_base_id | Hex-String u64 | Base ID for add-on content (DLC) | application_id + 0x1000 |
titles | Object of language titles | Language-specific application name/author values | Default values above |
presence_group_id | Hex-String u64 | Presence group ID | application_id |
save_data_owner_id | Hex-String u64 | Save-data owner ID | application_id |
isbn | String (max size 0x25) | ISBN | Empty string |
startup_user_account | "None", "Required", "RequiredWithNetworkServiceAccountAvailable" | Whether the application requires a user account on launch | "None" |
attribute | "None", "Demo", "RetailInteractiveDisplay" | Application attribute | "None" |
screenshot | "Allow", "Deny" | Screenshot control | "Allow" |
video_capture | "Disabled", "Enabled", "Automatic" | Video capture control | "Disabled" |
logo_type | "LicensedByNintendo", "Nintendo" | Logo type | "LicensedByNintendo" |
logo_handling | "Auto", "Manual" | Logo handling | "Auto" |
crash_report | "Deny", "Allow" | Crash report control | "Allow" |
bcat_passphrase | String (max size 0x41) | BCAT passphrase | Empty string |
program_index | u8 | Program index | 0 |
Note: default name/author and application ID are not actual NACP fields, but they are used as the default value for various fields, as the table shows.
Language names | Language codes |
---|---|
AmericanEnglish | en-US |
BritishEnglish | en-UK |
Japanese | ja |
French | fr |
German | de |
LatinAmericanSpanish | es-419 |
Spanish | es |
Italian | it |
Dutch | nl |
CanadianFrench | fr-CA |
Portuguese | pt |
Russian | ru |
Korean | ko |
TraditionalChinese | zh-TW |
SimplifiedChinese | zh-CN |
BrazilianPortuguese | pt-BR |
Note: languages in the titles object can be specified by their names or their codes, as the JSON example above shows.
- Example with specific languages:
[package]
name = "Multi-language"
version = "0.2.0"
authors = ["XorTroll"]
edition = "2021"
[package.metadata.nx.nro.nacp]
default_name = "A"
default_author = "B"
version = "0.2 beta"
titles = { ja = { name = "J" }, LatinAmericanSpanish = { author = "X" }, it = { name = "I", author = "T" } }
Names/authors produced above:
- Japanese: "J", "B"
- LatinAmericanSpanish: "A", "X"
- Italian: "I", "T"
- Other languages: "A", "B"
Note: only
name
andauthor
fields can be language-specific
Projects which generate sysmodule NSP exefs packages need a single, mandatory field for the NPDM data, which would be npdm
for specifying it on the TOML itself or npdm_json
for using an external JSON file:
- Example:
[package]
name = "Project"
version = "0.2.10"
authors = ["XorTroll"]
edition = "2021"
[package.metadata.nx.nsp.npdm]
name = "ProjectNpdm"
signature_key_generation = 0
main_thread_stack_size = "0x20000"
main_thread_priority = 49
main_thread_core_number = 3
system_resource_size = 0
version = 0
address_space_type = 1
is_64_bit = true
optimize_memory_allocation = false
disable_device_address_space_merge = false
is_production = true
unqualified_approval = false
memory_region = 2
program_id = "0x0100AAAABBBBCCCC"
[package.metadata.nx.nsp.npdm.fs_access_control]
flags = "0xFFFFFFFFFFFFFFFF"
[package.metadata.nx.nsp.npdm.service_access_control]
accessed_services = [ "fsp-srv", "ncm" ]
hosted_services = [ "demo:srv" ]
[package.metadata.nx.nsp.npdm.kernel_capabilities]
highest_priority = 63
lowest_priority = 16
max_core_number = 3
min_core_number = 3
enable_system_calls = [
"SetHeapSize"
]
kernel_version = "3.0"
- Example using an external NPDM JSON:
[package]
name = "Project"
version = "0.2.10"
authors = ["XorTroll"]
edition = "2021"
[package.metadata.nx.nsp]
npdm_json = "npdm.json"
Note: the NPDM JSON file follows the same format used in most other homebrews (check projects like Atmosphere, emuiibo, ldn_mitm...) and, like with the paths in the NRO format, it must be relative to the project's directory
Library projects have nothing special in their Cargo.toml
-
Implement more useful commands from regular
cargo build/new
, etc. -
Maybe bundle some basic target JSON+LDs different from the official tier 3 one? (32-bit or w/ crypto support, for instance)
- linkle libraries as the core element of this project
- cargo-count as the example followed to make a cargo subcommand project
- Icons8 for using one of their Nintendo Switch icons as the base for the default NRO icon