Initial commit

This commit is contained in:
Heath Mitchell 2023-07-21 00:56:24 +02:00
commit 1e74750f79
10 changed files with 252 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
# Build files
build-fx
build-cg
# GiteaPC support
giteapc-config.make

53
CMakeLists.txt Normal file
View File

@ -0,0 +1,53 @@
# libexample: build system
cmake_minimum_required(VERSION 3.16)
project(libexample VERSION 1.0 LANGUAGES C)
# Libraries that libexample depends on
find_package(Gint 2.1 REQUIRED)
# Turn include/example/config.h.in into a proper config.h where the @VAR@ have
# been replaced; this is how version numbers are maintained. libexample_VERSION
# is set to "1.0" by the project() command.
# Note that the input (config.h.in) is relative to the source dir, but the
# output (config.h) is in the build dir, so it doesn't pollute the Git repo.
configure_file(include/example/config.h.in include/example/config.h)
# With the target name "example", the output file will be called "libexample.a"
# (by default).
add_library(example STATIC src/add.c src/version.c)
# Find headers in the following directories:
# -> The include subfolder of the source
# -> The include subfolder of the build files (for config.h)
# This doesn't affect add-ins that *use* the library; flags for these are set
# in FindLibExample.cmake.
target_include_directories(example PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_BINARY_DIR}/include")
# After building, install the target (that is, libexample.a) in the fxSDK's
# sysroot which contains libraries for the calculator.
install(TARGETS example
DESTINATION "${FXSDK_LIB}")
# Install the headers. The contents of our include folder are added to the
# fxSDK's sysroot folder for headers. Since our headers are in an "example"
# subfolder, they will end up in ${FXSDK_INCLUDE}/example and users can include
# them as <example/*.h>.
#
# Note the / at the end of the source DIRECTORY, which indicates to copy the
# *contents* of include/ at the destination, not the folder itself.
#
# We only install files called "*.h" to exclude config.h.in.
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
DESTINATION "${FXSDK_INCLUDE}"
FILES_MATCHING PATTERN "*.h")
# Similarly, install config.h from the build dir.
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/example/config.h"
DESTINATION "${FXSDK_INCLUDE}/example")
# Install FindLibExample.cmake so that users can do find_package(LibExample).
install(FILES cmake/FindLibExample.cmake
DESTINATION "${FXSDK_CMAKE_MODULE_PATH}")

49
README.md Normal file
View File

@ -0,0 +1,49 @@
# libexample: A template gint library using CMake
This repository is a (Gitea template) example of how to build a library to use with [gint](/Lephenixnoir/gint). It uses the CMake build system added in [fxSDK 2.3](/Lephenixnoir/fxsdk).
Here's how the files are used:
* `src` and `include` are your library's code and headers. Unless you have a single header, you'll want to keep the compiler's include folder clean and have all your headers included as `<example/header.h>`, so `include` has a single subfolder `example`.
* There is a template header at `include/example/config.h.in` that gets transformed by CMake during build to insert the version number without hardcoding it. You can use it for other compile-time options.
* `CMakeLists.txt` is a pretty standard CMake script that builds the library.
* `cmake/FindLibExample.cmake` is a script for add-ins using your library, so that they can `find_package(LibExample 1.0)` and get all the compile and link options for free.
* `giteapc.make` makes it possible to build and install your library in a simple command using [GiteaPC](/Lephenixnoir/GiteaPC). If you don't want that you can delete it (along with the related `.gitignore` entries).
## The build system
Not a lot to discuss here, this is pretty standard. See the [tutorial on Planète Casio](https://www.planet-casio.com/Fr/forums/topic16647-1-tutoriel-compiler-des-add-ins-avec-cmake-fxsdk.html) (in French) for an introduction to CMake in the context of add-ins. You might be interested in [`configure_file()`](https://cmake.org/cmake/help/latest/command/configure_file.html) and [`install()`](https://cmake.org/cmake/help/latest/command/install.html), which are rarely used in add-ins.
The fxSDK provides three variables to help you install your files:
* `FXSDK_LIB` is the install path for library files (`*.a`).
* `FXSDK_INCLUDE` is the install path for headers (`*.h`); we use a subfolder `example/` to keep things organized.
* `FXSDK_CMAKE_MODULE_PATH` is the path of an fxSDK folder storing built-in and user-provided CMake modules. These are made visible to anyone that configures with `fxsdk build-{fx,cg}`.
## The FindPackage file
`cmake/FindLibExample.cmake` is a module used to search for libexample. The user would request to `find_package(LibExample)` and CMake will look for various options, one of which is a `Find<Package>.cmake` file in one of the search directories.
The goal of a find module is to determine whether the library is available, its version, and there are a couple of options. Most of these are handled by `find_package_handle_standard_args()`, including checking that the user-requested version and the installed version are compatible.
If the library is found, the find module defines an external target (called "imported") that provides the path to the library and suitable compile and link options. The user can run `target_link_libraries(addin LibExample::LibExample)` and all the flags will be supplied automatically. Whenever you update your library, the library file or the find module will change and all user applications will automatically relink.
The detection step is here automated with the fxSDK's [`FindSimpleLibrary.cmake`](/Lephenixnoir/fxsdk/src/branch/master/fxsdk/cmake/FindSimpleLibrary.cmake) module.
## GiteaPC support
[GiteaPC](/Lephenixnoir/GiteaPC) is a tool to automate building and installing repositories from the Planète Casio Gitea forge. It was designed to speed up library management in the fxSDK. A repository that has the `giteapc` topic (topics can be added through the "Manage topics" link on the repository's front page) and provides `giteapc.make` can be built, installed, and updated with a simple command.
```
% giteapc install Lephenixnoir/Template-gint-library
```
The job of `giteapc.make` is simply to provide configure, build, install and uninstall commands. CMake [does not support uninstall targets](https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake), but we can simply remove the files that CMake has recorded installing. This might leave empty directories, but it's a good start.
`giteapc.make` can also specify basic dependencies in the top comment.
The `giteapc-config.make` file is for the user to customize the build by adding environment variables (such as setting `LIBEXAMPLE_CMAKEOPTS_FX` to change compiler behaviour, or anything they might need). You can provide configurations of your own in `giteapc-config-<name>.cmake` (they can be installed with `giteapc install Lephenixnoir/Template-gint-library:name`). See [sh-elf-gcc](/Lephenixnoir/sh-elf-gcc) for an example of custom configurations.
## License
All the files in this repository are [licensed under CC0](https://creativecommons.org/publicdomain/zero/1.0/); you can use them in any way you want under no conditions whatsoever (this is compatible with the GPL : [[1]](https://wiki.creativecommons.org/wiki/CC0_FAQ#May_I_apply_CC0_to_computer_software.3F_If_so.2C_is_there_a_recommended_implementation.3F), [[2]](https://www.gnu.org/licenses/license-list.html#PublicDomain)).

View File

@ -0,0 +1,47 @@
find_package(Gint 2.1 REQUIRED)
# Ask the fxSDK to find a library called libexample.a, and find its version in
# the macro EX_VERSION of the header file <example/config.h>.
#
# Store the path to libexample.a in EX_PATH and store the version number in
# EX_VERSION.
include(FindSimpleLibrary)
find_simple_library(libexample.a example/config.h "EX_VERSION"
PATH_VAR EX_PATH
VERSION_VAR EX_VERSION)
# The fxSDK looks for libexample.a in ${FXSDK_LIB}, then <example/config.h> in
# ${FXSDK_INCLUDE}, and extracts the version number from a macro like
#
# #define EX_VERSION "..."
#
# See the source code for the FindSimpleLibrary module for more detail.
# We then use a CMake function to finish searching the library. We specify:
# * REQUIRED_VARS ... which requires the variables to be non-empty, otherwise
# find_library() says the library was not found.
# * VERSION_VAR ... which provides the version number, so that find_library()
# can compare with the version requested by the user (if any) and fail if
# the version we found isn't compatible.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibExample
REQUIRED_VARS EX_PATH EX_VERSION
VERSION_VAR EX_VERSION)
# We now have a LibExample_FOUND variable indicating if everything went well.
# If so we can now create an *imported target* that is not built in the project
# but can still be linked against with target_link_libraries().
if(LibExample_FOUND)
# This is an imported target, we don't build it, we just claim it's here.
add_library(LibExample::LibExample UNKNOWN IMPORTED)
# Here we declare the compiler and linker flags that every user of LibExample
# needs to use.
set_target_properties(LibExample::LibExample PROPERTIES
# If we specify where the library comes from, CMake will watch that file
# and relink any user application when the library is updated!
IMPORTED_LOCATION "${EX_PATH}"
# Linking options
INTERFACE_LINK_OPTIONS -lexample
# Dependencies (for order on the command-line)
INTERFACE_LINK_LIBRARIES Gint::Gint)
endif()

25
giteapc.make Normal file
View File

@ -0,0 +1,25 @@
# giteapc: version=1 depends=Lephenixnoir/gint
-include giteapc-config.make
configure:
@ fxsdk build-fx -c $(LIBEXAMPLE_CMAKEOPTS_FX)
@ fxsdk build-cg -c $(LIBEXAMPLE_CMAKEOPTS_CG)
build:
@ fxsdk build-fx
@ fxsdk build-cg
install:
@ fxsdk build-fx install
@ fxsdk build-cg install
uninstall:
@ if [ -e build-fx/install_manifest.txt ]; then \
xargs rm -f < build-fx/install_manifest.txt; \
fi
@ if [ -e build-cg/install_manifest.txt ]; then \
xargs rm -f < build-cg/install_manifest.txt; \
fi
.PHONY: configure build install uninstall

16
include/example/add.h Normal file
View File

@ -0,0 +1,16 @@
/* libexample: add utilities */
#ifndef _EXAMPLE_ADD
#define _EXAMPLE_ADD
#ifdef __cplusplus
extern "C" {
#endif
int ex_add(int x, int y);
#ifdef __cplusplus
}
#endif
#endif /* _EXAMPLE_ADD */

View File

@ -0,0 +1,9 @@
/* libexample: compile-time configuration */
#ifndef _EXAMPLE_CONFIG
#define _EXAMPLE_CONFIG
/* The @VAR@ notation is substituted by CMake */
#define EX_VERSION "@libexample_VERSION@"
#endif /* _EXAMPLE_CONFIG */

23
include/example/version.h Normal file
View File

@ -0,0 +1,23 @@
/* libexample: version information */
#ifndef _EXAMPLE_VERSION
#define _EXAMPLE_VERSION
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/* Version of the example library */
char const *ex_version(void);
/* Version of gint used in this library */
char const *ex_gint_version(void);
uint32_t ex_gint_hash(void);
#ifdef __cplusplus
}
#endif
#endif /* _EXAMPLE_VERSION */

6
src/add.c Normal file
View File

@ -0,0 +1,6 @@
#include <example/add.h>
int ex_add(int x, int y)
{
return x + y;
}

18
src/version.c Normal file
View File

@ -0,0 +1,18 @@
#include <example/version.h>
#include <example/config.h>
#include <gint/config.h>
char const *ex_version(void)
{
return EX_VERSION;
}
char const *ex_gint_version(void)
{
return GINT_VERSION;
}
uint32_t ex_gint_hash(void)
{
return GINT_HASH;
}