aarch64-switch-rs/cargo-nx

Cargo subcommand to simplify building Nintendo Switch projects

94

stars

19

commits

Rust

primary language

Jun 25, 2025

updated

hacktoberfest

README

cargo-nx

Introduction

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.

Installation

Assuming you have Rust and cargo installed, it's just a matter of two steps:

  1. If not already installed, install rust-src:

    rustup component add rust-src
    
  2. Install cargo-nx:

    cargo install cargo-nx --git https://github.com/aarch64-switch-rs/cargo-nx
    

Usage

The program can be executed as cargo-nx or simply as a cargo subcommand, cargo nx, and it provides the following main subcommands:

new subcommand

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, and nsp are available, with nro being the default.

build subcommand

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 normal cargo build --release option.

  • -p <path>, --path=<path>: Specifies a path with a crate to build (containing Cargo.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 regular cargo build); "aarch64-nintendo-switch-freestanding" (official tier 3 target) is used by default.

  • -v, --verbose: Displays extra information during the build process.

Package formats

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.

NRO

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 and icon 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:

FieldValueDescriptionDefault value
default_nameString (max size 0x200)Default title nameUnknown application
default_authorString (max size 0x100)Default application authorUnknown author
versionString (max size 0x10)Application version
application_idHex-String u64Application ID0000000000000000
add_on_content_base_idHex-String u64Base ID for add-on content (DLC)application_id + 0x1000
titlesObject of language titlesLanguage-specific application name/author valuesDefault values above
presence_group_idHex-String u64Presence group IDapplication_id
save_data_owner_idHex-String u64Save-data owner IDapplication_id
isbnString (max size 0x25)ISBNEmpty 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_passphraseString (max size 0x41)BCAT passphraseEmpty string
program_indexu8Program index0

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.

Available languages

Language namesLanguage codes
AmericanEnglishen-US
BritishEnglishen-UK
Japaneseja
Frenchfr
Germande
LatinAmericanSpanishes-419
Spanishes
Italianit
Dutchnl
CanadianFrenchfr-CA
Portuguesept
Russianru
Koreanko
TraditionalChinesezh-TW
SimplifiedChinesezh-CN
BrazilianPortuguesept-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 and author fields can be language-specific

NSP

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

Libraries

Library projects have nothing special in their Cargo.toml

TODO

  • 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)

Credits

  • 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

Contributors

XorTroll

8 commits

pantsman0

5 commits

LNSD

3 commits

Absolucy

2 commits

aarch64-switch-rs/cargo-nx

Cargo subcommand to simplify building Nintendo Switch projects

94

stars

19

commits

Rust

primary language

Jun 25, 2025

updated

hacktoberfest

README

cargo-nx

Introduction

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.

Installation

Assuming you have Rust and cargo installed, it's just a matter of two steps:

  1. If not already installed, install rust-src:

    rustup component add rust-src
    
  2. Install cargo-nx:

    cargo install cargo-nx --git https://github.com/aarch64-switch-rs/cargo-nx
    

Usage

The program can be executed as cargo-nx or simply as a cargo subcommand, cargo nx, and it provides the following main subcommands:

new subcommand

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, and nsp are available, with nro being the default.

build subcommand

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 normal cargo build --release option.

  • -p <path>, --path=<path>: Specifies a path with a crate to build (containing Cargo.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 regular cargo build); "aarch64-nintendo-switch-freestanding" (official tier 3 target) is used by default.

  • -v, --verbose: Displays extra information during the build process.

Package formats

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.

NRO

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 and icon 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:

FieldValueDescriptionDefault value
default_nameString (max size 0x200)Default title nameUnknown application
default_authorString (max size 0x100)Default application authorUnknown author
versionString (max size 0x10)Application version
application_idHex-String u64Application ID0000000000000000
add_on_content_base_idHex-String u64Base ID for add-on content (DLC)application_id + 0x1000
titlesObject of language titlesLanguage-specific application name/author valuesDefault values above
presence_group_idHex-String u64Presence group IDapplication_id
save_data_owner_idHex-String u64Save-data owner IDapplication_id
isbnString (max size 0x25)ISBNEmpty 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_passphraseString (max size 0x41)BCAT passphraseEmpty string
program_indexu8Program index0

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.

Available languages

Language namesLanguage codes
AmericanEnglishen-US
BritishEnglishen-UK
Japaneseja
Frenchfr
Germande
LatinAmericanSpanishes-419
Spanishes
Italianit
Dutchnl
CanadianFrenchfr-CA
Portuguesept
Russianru
Koreanko
TraditionalChinesezh-TW
SimplifiedChinesezh-CN
BrazilianPortuguesept-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 and author fields can be language-specific

NSP

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

Libraries

Library projects have nothing special in their Cargo.toml

TODO

  • 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)

Credits

  • 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

Contributors

XorTroll

8 commits

pantsman0

5 commits

LNSD

3 commits

Absolucy

2 commits

Languages

Rust

100.0%