CMake scripts for devkitArm and 3DS and GBA homebrew development.
It aims to provide at least the same functionalities as the devkitPro makefiles. It can help to build more complex projects or simply compile libraries by using the toolchain file.
- How to use it?
- 3DS CMake files
- The toolchain file (DevkitArm3DS.cmake)
- FindCTRULIB.cmake
- FindCITRO3D.cmake
- FindSF2D.cmake
- FindSFTD.cmake
- FindSFIL.cmake
- FindZLIB.cmake
- FindPNG.cmake
- FindJPEG.cmake
- FindFreetype.cmake
- Tools3DS.cmake
- add_3dsx_target
- add_cia_target(target RSF IMAGE SOUND [APP_TITLE APP_DESCRIPTION APP_AUTHOR [APP_ICON]])
- add_cci_target(target RSF IMAGE SOUND [APP_TITLE APP_DESCRIPTION APP_AUTHOR [APP_ICON]])
- add_netload_target(name target_or_file)
- add_binary_library(target input1 [input2 ...])
- target_embed_file(target input1 [input2 ...])
- add_shbin(output input [entrypoint][shader_type])
- generate_shbins(input1 [input2 ...])
- add_shbin_library(target input1 [input2 ...])
- target_embed_shader(target input1 [input2 ...])
- Example of CMakeLists.txt using ctrulib and shaders
- GBA CMake files
Simply copy DevkitArm3DS.cmake
and the cmake
folder at the root of your project (where your CMakeLists.txt is). Then start cmake with
cmake -DCMAKE_TOOLCHAIN_FILE=DevkitArm3DS.cmake
Or, put the following at the top of your CMakeLists.txt
file:
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/DevkitArm3DS.cmake)
Simply copy DevkitArmGBA.cmake
and the cmake
folder at the root of your project (where your CMakeLists.txt is). Then start cmake with
cmake -DCMAKE_TOOLCHAIN_FILE=DevkitArmGBA.cmake
Or, put the following at the top of your CMakeLists.txt
file:
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/DevkitArmGBA.cmake)
If you are on windows, I suggest using the Unix Makefiles
generator.
cmake-gui
is also a good alternative, you can specify the toolchain file the first time you configure a build.
You can use the macros and find scripts of the cmake
folder by adding the following line to your CMakeLists.cmake :
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
This CMake variable will be set so that you can test against it for projects that can be built on other platforms.
This CMake variable is set to -fomit-frame-pointer -ffunction-sections
. Those are the recommended C flags for devkitArm projects but are non-mandatory.
This CMake variable is set to -fomit-frame-pointer -ffunction-sections -fno-rtti -fno-exceptions -std=gnu 11
. Those are the recommended C flags for devkitArm projects but are non-mandatory.
By default the portlibs folder will be used, it can be disabled by changing the value of WITH_PORTLIBS to OFF from the cache (or forcing the value from your CMakeLists.txt).
find_package(CTRULIB [REQUIRED])
You can optionally set the following before calling find_package
:
CTRULIB_ROOT
- the root directory of your CTRULIB install.
If CTRULIB is found it will set the following:
CTRULIB_FOUND
CTRULIB_LIBRARIES
- the necessary libraries to link against to use CTRULIB.CTRULIB_INCLUDE_DIRS
- the necessary include directories to use CTRULIB.- It will also add an imported target named
3ds::ctrulib
.
Examples of linking against CTRULIB:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(CTRULIB REQUIRED)
target_link_libraries(mytarget ${CTRULIB_LIBRARIES})
target_include_directories(mytarget PRIVATE ${CTRULIB_INCLUDE_DIRS})
- Using the imported target:
find_package(CTRULIB REQUIRED)
target_link_libraries(mytarget 3ds::ctrulib)
find_package(CITRO3D [REQUIRED])
You can optionally set the following before calling find_package
:
CITRO3D_ROOT
- the root directory of your CITRO3D install.
CITRO3D also depends on the following being found:
If CITRO3D is found it will set the following:
CITRO3D_FOUND
CITRO3D_LIBRARIES
- the necessary libraries to link against to use CITRO3D (including CTRULIB).CITRO3D_INCLUDE_DIRS
- the necessary include directories to use CITRO3D (including CTRULIB).- It will also add an imported target named
3ds::citro3d
.- This automatically links against
3ds::ctrulib
andm
as well.
- This automatically links against
Examples of linking against CITRO3D:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(CITRO3D REQUIRED)
target_link_libraries(mytarget ${CITRO3D_LIBRARIES})
target_include_directories(mytarget PRIVATE ${CITRO3D_INCLUDE_DIRS})
- Using the imported target:
find_package(CITRO3D REQUIRED)
target_link_libraries(mytarget 3ds::citro3d)
find_package(SF2D [REQUIRED])
You can optionally set the following before calling find_package
:
SF2D_ROOT
- the root directory of your SF2D install.
SF2D also depends on the following being found:
If SF2D is found it will set the following:
SF2D_FOUND
SF2D_LIBRARIES
- the necessary libraries to link against to use SF2D (including CITRO3D etc.).SF2D_INCLUDE_DIRS
- the necessary include directories to use SF2D (including CITRO3D etc.).- It will also add an imported target named
3ds::sf2d
.- This automatically links against
3ds::citro3d
as well.
- This automatically links against
Examples of linking against SF2D:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(SF2D REQUIRED)
target_link_libraries(mytarget ${SF2D_LIBRARIES})
target_include_directories(mytarget PRIVATE ${SF2D_INCLUDE_DIRS})
- Using the imported target:
find_package(SF2D REQUIRED)
target_link_libraries(mytarget 3ds::sf2d)
find_package(SFTD [REQUIRED])
You can optionally set the following before calling find_package
:
SFTD_ROOT
- the root directory of your SFTD install.
SFTD also depends on the following being found:
If SFTD is found it will set the following:
SFTD_FOUND
SFTD_LIBRARIES
- the necessary libraries to link against to use SFTD (including Freetype and SF2D etc.).SFTD_INCLUDE_DIRS
- the necessary include directories to use SFTD (including Freetype and SF2D etc.).- It will also add an imported target named
3ds::sftd
.- This automatically links against
3ds::freetype
and3ds::sf2d
as well.
- This automatically links against
Examples of linking against SFTD:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(SFTD REQUIRED)
target_link_libraries(mytarget ${SFTD_LIBRARIES})
target_include_directories(mytarget PRIVATE ${SFTD_INCLUDE_DIRS})
- Using the imported target:
find_package(SFTD REQUIRED)
target_link_libraries(mytarget 3ds::sftd)
find_package(SFIL [REQUIRED])
You can optionally set the following before calling find_package
:
SFIL_ROOT
- the root directory of your SFIL install.
SFIL also depends on the following being found:
If SFIL is found it will set the following:
SFIL_FOUND
SFIL_LIBRARIES
- the necessary libraries to link against to use SFIL (including PNG, JPEG and SF2D etc.).SFIL_INCLUDE_DIRS
- the necessary include directories to use SFIL (including PNG, JPEG and SF2D etc.).- It will also add an imported target named
3ds::sfil
.- This automatically links against
3ds::png
,3ds::jpeg
and3ds::sf2d
as well.
- This automatically links against
Examples of linking against SFIL:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(SFIL REQUIRED)
target_link_libraries(mytarget ${SFIL_LIBRARIES})
target_include_directories(mytarget PRIVATE ${SFIL_INCLUDE_DIRS})
- Using the imported target:
find_package(SFIL REQUIRED)
target_link_libraries(mytarget 3ds::sfil)
find_package(ZLIB [REQUIRED])
You can optionally set the following before calling find_package
:
ZLIB_ROOT
- the root directory of your ZLIB install.
As this is a portlib, this is almost certainly fail to find ZLIB if WITH_PORTLIBS
is set to OFF, unless you set ZLIB_ROOT
.
If ZLIB is found it will set the following:
ZLIB_FOUND
ZLIB_LIBRARIES
- the necessary libraries to link against to use ZLIB.ZLIB_INCLUDE_DIRS
- the necessary include directories to use ZLIB.- It will also add an imported target named
3ds::zlib
.
Examples of linking against ZLIB:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(ZLIB REQUIRED)
target_link_libraries(mytarget ${ZLIB_LIBRARIES})
target_include_directories(mytarget PRIVATE ${ZLIB_INCLUDE_DIRS})
- Using the imported target:
find_package(ZLIB REQUIRED)
target_link_libraries(mytarget 3ds::zlib)
find_package(PNG [REQUIRED])
You can optionally set the following before calling find_package
:
PNG_ROOT
- the root directory of your PNG install.
As this is a portlib, this is almost certainly fail to find PNG if WITH_PORTLIBS
is set to OFF, unless you set PNG_ROOT
.
PNG also depends on the following being found:
If PNG is found it will set the following:
PNG_FOUND
PNG_LIBRARIES
- the necessary libraries to link against to use PNG (including ZLIB).PNG_INCLUDE_DIRS
- the necessary include directories to use PNG (including ZLIB).- It will also add an imported target named
3ds::png
.- This automatically links against
3ds::zlib
andm
as well.
- This automatically links against
Examples of linking against PNG:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(PNG REQUIRED)
target_link_libraries(mytarget ${PNG_LIBRARIES})
target_include_directories(mytarget PRIVATE ${PNG_INCLUDE_DIRS})
- Using the imported target:
find_package(PNG REQUIRED)
target_link_libraries(mytarget 3ds::png)
find_package(JPEG [REQUIRED])
You can optionally set the following before calling find_package
:
JPEG_ROOT
- the root directory of your JPEG install.
As this is a portlib, this is almost certainly fail to find JPEG if WITH_PORTLIBS
is set to OFF, unless you set JPEG_ROOT
.
If JPEG is found it will set the following:
JPEG_FOUND
JPEG_LIBRARIES
- the necessary libraries to link against to use JPEG.JPEG_INCLUDE_DIRS
- the necessary include directories to use JPEG.- It will also add an imported target named
3ds::jpeg
.
Examples of linking against JPEG:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(JPEG REQUIRED)
target_link_libraries(mytarget ${JPEG_LIBRARIES})
target_include_directories(mytarget PRIVATE ${JPEG_INCLUDE_DIRS})
- Using the imported target:
find_package(JPEG REQUIRED)
target_link_libraries(mytarget 3ds::jpeg)
find_package(Freetype [REQUIRED])
You can optionally set the following before calling find_package
:
Freetype_ROOT
- the root directory of your Freetype install.
As this is a portlib, this is almost certainly fail to find Freetype if WITH_PORTLIBS
is set to OFF, unless you set Freetype_ROOT
.
PNG also depends on the following being found:
If Freetype is found it will set the following:
Freetype_FOUND
Freetype_LIBRARIES
- the necessary libraries to link against to use Freetype (including ZLIB).Freetype_INCLUDE_DIRS
- the necessary include directories to use Freetype (including ZLIB).- It will also add an imported target named
3ds::freetype
.- This automatically links against
3ds::zlib
as well.
- This automatically links against
Examples of linking against Freetype:
- Using
_LIBRARIES
and_INCLUDE_DIRS
:
find_package(Freetype REQUIRED)
target_link_libraries(mytarget ${Freetype_LIBRARIES})
target_include_directories(mytarget PRIVATE ${Freetype_INCLUDE_DIRS})
- Using the imported target:
find_package(Freetype REQUIRED)
target_link_libraries(mytarget 3ds::freetype)
This file must be included with include(Tools3DS)
. It provides several macros related to 3DS development such as add_shader_library
which assembles your shaders into a C library.
This macro has two signatures :
Adds a target that generates a .3dsx file from target
. If NO_SMDH is specified, no .smdh file will be generated.
You can set the following variables to change the SMDH file :
- APP_TITLE is the name of the app stored in the SMDH file (Optional)
- APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
- APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
- APP_ICON is the filename of the icon (.png), relative to the project folder.
If not set, it attempts to use one of the following (in this order):
- $(target).png
- icon.png
- $(libctru folder)/default_icon.png
This version will produce the SMDH with the values passed as arguments. The APP_ICON is optional and follows the same rule as the other version of add_3dsx_target
.
Same as add_3dsx_target but for CIA files.
- RSF is the .rsf file to be given to makerom.
- IMAGE is either a .png or a cgfximage file.
- SOUND is either a .wav or a cwavaudio file.
Same as add_cia_target but for CCI files.
Adds a target name
that sends a .3dsx using the homebrew launcher netload system (3dslink).
target_or_file
is either the name of a target (on which you used add_3dsx_target) or a file name.
/!\ Requires ASM to be enabled ( enable_language(ASM)
or
project(yourprojectname C CXX ASM)
)
Converts the files given as input to arrays of their binary data. This is useful to embed resources into your project. For example, logo.bmp will generate the array u8 logo_bmp[]
and its size logo_bmp_size
. By linking this library, you will also have access to a generated header file called logo_bmp.h
which contains the declarations you need to use it.
Note : All dots in the filename are converted to _
, and if it starts with a number, _
will be prepended. For example 8x8.gas.tex
would give the name _8x8_gas_tex
.
This is the same as:
add_binary_library(tempbinlib input1 [input2 ...])
target_link_libraries(target tempbinlib)
Assembles the shader given as input
into the file output
. No file extension is added. You can choose the shader assembler by setting SHADER_AS to picasso
or nihstro
.
If nihstro
is set as the assembler, entrypoint and shader_type will be used.
- entrypoint is set to
main
by default - shader_type can be either VSHADER or GSHADER. By default it is VSHADER.
Assemble all the shader files given as input into .shbin files. Those will be located in the folder shaders
of the build directory. The names of the output files will be
<name of input without shortest extension>.shbin
. shader.pica
will output shader.shbin
but shader.vertex.pica
will output shader.vertex.shbin
.
/!\ Requires ASM to be enabled ( enable_language(ASM)
or
project(yourprojectname C CXX ASM)
)
This is the same as:
generate_shbins(source/shader.vertex.pica)
add_binary_library(target ${CMAKE_CURRENT_BINARY_DIR}/shaders/shader.vertex.shbin)
This is the function to be used to reproduce devkitArm makefiles behaviour. For example, add_shbin_library(shaders data/my1stshader.vsh.pica) will generate the target library shaders
and you will be able to use the shbin in your program by linking it, including my1stshader_pica.h
and using my1stshader_pica[]
and my1stshader_pica_size
.
This is the same as:
add_shbin_library(tempbinlib input1 [input2 ...])
target_link_libraries(target tempbinlib)
cmake_minimum_required(VERSION 2.8)
project(hello_cmake C CXX ASM)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
include(Tools3DS)
find_package(CTRULIB REQUIRED)
file(GLOB_RECURSE SHADERS_FILES
data/*.pica
)
add_shbin_library(shaders ${SHADERS_FILES})
file(GLOB_RECURSE SOURCE_FILES
source/*
)
add_executable(hello_cmake ${SOURCE_FILES})
target_link_libraries(hello_cmake shaders 3ds::ctrulib)
add_3dsx_target(hello_cmake)
This CMake variable will be set so that you can test against it for projects that can be built on other platforms.
This CMake variable is set to -fomit-frame-pointer -ffast-math
. Those are the recommended C flags for devkitArm projects but are non-mandatory.
This CMake variable is set to -fomit-frame-pointer -ffast-math -fno-rtti -fno-exceptions
. Those are the recommended C flags for devkitArm projects but are non-mandatory.
By default the portlibs folder will be used, it can be disabled by changing the value of WITH_PORTLIBS to OFF from the cache (or forcing the value from your CMakeLists.txt).
This file must be included with include(ToolsGBA)
. It provides several macros related to GBA development.
Will generate a .gba file from the elf_executable.
/!\ Requires ASM to be enabled ( enable_language(ASM)
or
project(yourprojectname C CXX ASM)
)
Converts the files given as input to arrays of their binary data. This is useful to embed resources into your project. For example, logo.bmp will generate the array u8 logo_bmp[]
and its size logo_bmp_size
. By linking this library, you will also have access to a generated header file called logo_bmp.h
which contains the declarations you need to use it.
Note : All dots in the filename are converted to _
, and if it starts with a number, _
will be prepended. For example 8x8.gas.tex
would give the name _8x8_gas_tex
.
This is the same as:
add_binary_library(tempbinlib input1 [input2 ...])
target_link_libraries(target tempbinlib)
Will generate a soundbank file for the MaxMOD music player from sound_files and add it to elf_executable.
cmake_minimum_required(VERSION 3.1.0)
# Note that you must copy the cmake folder and the DevkitArmGBA.cmake file in this directory
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/DevkitArmGBA.cmake)
# Add the cmake folder to the modules paths, so that we can use the tools
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
# ASM must be enabled to support .S files
enable_language(ASM)
# Include all the macros and tools needed for GBA development.
include(ToolsGBA)
project(hello_world)
# List all the source files in our directory
LIST(APPEND SOURCE_FILES
./main.cpp
./memcpy.s
)
# List all the data files to be included
LIST(APPEND EXTRA_DATA_FILES
./data/dkp_logo.c
)
# List all libGBA directories
LIST(APPEND INCLUDE_DIRECTORIES
${DEVKITPRO}/libgba/include
${DEVKITARM}/arm-none-eabi/include/
)
# List all library directories
LIST(APPEND TARGET_LIBRARIES
${DEVKITPRO}/libgba/lib
)
link_directories(${TARGET_LIBRARIES})
include_directories(${INCLUDE_DIRECTORIES})
# Create elf file
add_executable(hello_world.elf ${SOURCE_FILES} ${INCLUDE_FILES} ${EXTRA_DATA_FILES})
# Generate the .gba from the elf
add_gba_executable(hello_world.elf)
# Link the application, libgba and maxmod
target_link_libraries(hello_world.elf gba mm)
# List all the MaxMOD music files
file(GLOB_RECURSE MUSIC_FILES
./music/*
)
# Build soundbank file from music files
target_maxmod_file(hello_world.elf ${MUSIC_FILES})
# List all the binary data files to be included
file(GLOB_RECURSE DATA_FILES
./data/*.bin
)