From d79f3faca64a7afb9bb4f69c96cff50b337d941e Mon Sep 17 00:00:00 2001 From: Andy Alt Date: Fri, 2 Apr 2021 16:34:14 -0500 Subject: [PATCH] improve the install system, add three tests (#21) * install system:allow the use of --datadir... Also some other improvements were made. DESTDIR and @datadir@ was not being used properly in the Makefile * move some functions from config_h.rs.in to config.rs * provide some instructions in the README on how to build and run without having to use autoconf and ./configure * add 'install-strip' target to Makefile * install docs * remove 'clean' target (use distclean instead) * simply install example in README * add a few tests to the source code (get_icon, access_card, access_pixmap) * remove empty dirs when uninstalling * add release target to Makefile, check for cargo bin existence * install even if cargo binary not found (for sudo installations when cargo isn't installed for the root user) --- .github/workflows/rust.yml | 6 +-- Makefile.in | 96 ++++++++++++++++++++++++-------------- README.md | 21 +++++++-- configure.ac | 50 +++++++++++++++++++- src/config.rs | 43 +++++++++++++++++ src/config_h.rs.in | 25 +--------- src/gui/asset_manager.rs | 16 +++++-- src/main.rs | 3 +- 8 files changed, 186 insertions(+), 74 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index cced72c..a51f176 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,12 +30,10 @@ jobs: - run: autoconf # the prefix is later used for 'make install' (unless using sudo, the # target directory needs to have normal user write permissions). - - run: ./configure --prefix=$PWD + - run: ./configure --prefix=$PWD/install_test - run: cargo update # Now build to make sure a `cargo update` won't change results of the -# build. The install target looks for a release build, so going to first -# build with the --release flag. - - run: cargo build --release +# build. - run: make install - run: make uninstall diff --git a/Makefile.in b/Makefile.in index 1080623..baeaf67 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,5 +1,3 @@ -datarootdir = @datarootdir@ - # DESTDIR will get overridden when it's is used with 'make' # (e.g. `make DESTDIR= {install, uninstall}`). # @@ -12,8 +10,6 @@ datarootdir = @datarootdir@ # 'uninstall' to work. # See https://www.gnu.org/prep/standards/html_node/DESTDIR.html for more information. # -DESTDIR=@prefix@ -BIN_DEST=$(DESTDIR)/games CARD_FILES = \ LICENSE \ @@ -72,59 +68,87 @@ CARD_FILES = \ QS.svg \ KS.svg \ - -CLEAN_FILES = \ - telluricdeckay.desktop \ - telluricdeckay.appdata.xml \ - config_h.rs +DOC_FILES = \ + README.md \ + CONTRIBUTING.md \ + Cargo.toml \ + LICENSE-MIT \ + LICENSE-APACHE DISTCLEAN_FILES = \ Makefile \ config.status \ - config.log + config.log \ + @PACKAGE_TARNAME@.desktop \ + @PACKAGE_TARNAME@.appdata.xml \ + src/config_h.rs -devbuild: - cargo build +DIRS = \ + $(DESTDIR)@DATADIR@/@PACKAGE_TARNAME@/cards \ + $(DESTDIR)@DATADIR@/@PACKAGE_TARNAME@ \ + $(DESTDIR)@DATADIR@/pixmaps \ + $(DESTDIR)@DATADIR@/applications \ + $(DESTDIR)@DATADIR@/appdata \ + $(DESTDIR)@DOCDIR@/@PACKAGE_TARNAME@ \ + $(DESTDIR)@DOCDIR@ \ + $(DESTDIR)@DATADIR@ \ + $(DESTDIR)@BINDIR@ \ + $(DESTDIR)@prefix@ -build: - # The cargo binary can't be found when `sudo` is used to `make install` - # You'll need to run 'cargo build --release' to update the binary. +release: + if test $$(command -v cargo); then \ + cargo build --release; \ + else \ + echo "\n! Warning: cargo binary not found; release target not rebuilt.\n"; \ + fi -install: build - install -D -s -m 0755 ./target/release/telluricdeckay -t $(BIN_DEST) - install -D -m 0644 ./assets/cards/* -t $(DESTDIR)@datadir@/telluricdeckay/assets/cards - install -D -m 0644 ./telluricdeckay.appdata.xml -t $(DESTDIR)@datadir@/appdata - install -D -m 0644 ./telluricdeckay.desktop -t $(DESTDIR)@datadir@/applications - install -D -m 0644 ./assets/telluricdeckay.png -t $(DESTDIR)@datadir@/pixmaps +install: release + install -D -s -m 0755 ./target/release/@PACKAGE_TARNAME@ -t $(DESTDIR)@BINDIR@ + install -D -m 0644 ./assets/cards/* -t $(DESTDIR)@DATADIR@/@PACKAGE_TARNAME@/cards + install -D -m 0644 ./@PACKAGE_TARNAME@.appdata.xml -t $(DESTDIR)@DATADIR@/appdata + install -D -m 0644 ./@PACKAGE_TARNAME@.desktop -t $(DESTDIR)@DATADIR@/applications + install -D -m 0644 ./assets/@PACKAGE_TARNAME@.png -t $(DESTDIR)@DATADIR@/pixmaps + install -d $(DESTDIR)@DOCDIR@/@PACKAGE_TARNAME@ + for file in $(DOC_FILES); do \ + install -D -m 0644 $$file $(DESTDIR)@DOCDIR@/@PACKAGE_TARNAME@; \ + done + +install-strip: install + strip $(DESTDIR)@BINDIR@/@PACKAGE_TARNAME@ uninstall: - if test -f $(BIN_DEST)/telluricdeckay; then \ - $(RM) $(BIN_DEST)/telluricdeckay; \ + if test -f $(DESTDIR)@BINDIR@/@PACKAGE_TARNAME@; then \ + $(RM) $(DESTDIR)@BINDIR@/@PACKAGE_TARNAME@; \ fi; \ - if test -f $(DESTDIR)@datadir@/appdata/telluricdeckay.appdata.xml; then \ - $(RM) $(DESTDIR)@datadir@/appdata/telluricdeckay.appdata.xml; \ + if test -f $(DESTDIR)@DATADIR@/appdata/@PACKAGE_TARNAME@.appdata.xml; then \ + $(RM) $(DESTDIR)@DATADIR@/appdata/@PACKAGE_TARNAME@.appdata.xml; \ fi; \ - if test -f $(DESTDIR)@datadir@/applications/telluricdeckay.desktop; then \ - $(RM) $(DESTDIR)@datadir@/applications/telluricdeckay.desktop; \ + if test -f $(DESTDIR)@DATADIR@/applications/@PACKAGE_TARNAME@.desktop; then \ + $(RM) $(DESTDIR)@DATADIR@/applications/@PACKAGE_TARNAME@.desktop; \ fi; \ - if test -f $(DESTDIR)@datadir@/pixmaps/telluricdeckay.png; then \ - $(RM) $(DESTDIR)@datadir@/pixmaps/telluricdeckay.png; \ + if test -f $(DESTDIR)@DATADIR@/pixmaps/@PACKAGE_TARNAME@.png; then \ + $(RM) $(DESTDIR)@DATADIR@/pixmaps/@PACKAGE_TARNAME@.png; \ fi; \ for card in $(CARD_FILES); do \ - file="$(DESTDIR)@datadir@/telluricdeckay/assets/cards/"$$card; \ + file="$(DESTDIR)@DATADIR@/@PACKAGE_TARNAME@/cards/"$$card; \ if test -f $$file; then \ $(RM) $$file; \ fi; \ done - -clean: - for file in $(CLEAN_FILES); do \ - if test -f $$file; then \ - $(RM) $$file; \ + for file in $(DOC_FILES); do \ + if test -f "$(DESTDIR)@DOCDIR@/@PACKAGE_TARNAME@/"$$file; then \ + $(RM) "$(DESTDIR)@DOCDIR@/@PACKAGE_TARNAME@/"$$file; \ + fi; \ + done + for dir in $(DIRS); do \ + if test -d $$dir; then \ + if test -z "$$(ls -1qA $$dir)"; then \ + rmdir $$dir; \ + fi; \ fi; \ done -distclean: clean +distclean: for file in $(DISTCLEAN_FILES); do \ if test -f $$file; then \ $(RM) $$file; \ diff --git a/README.md b/README.md index 64e9525..8d49cf8 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ In early development, not ready for use yet ## Build and Run +If you only want to build and run, but not install, just copy +'config_h.rs.in' to config_h.rs, open with an editor, and replace +"@DATADIR@" with "/usr/local/share" (or some other arbitrary directory). You +can then skip the first two steps listed below. + autoconf ./configure cargo build @@ -17,7 +22,9 @@ In early development, not ready for use yet ## Installation -No distribution packages are available. To install from source: +No distribution packages are available. Installation is not required to +run the game and is primarily intended for packagers or anyone who +wants to install a release. autoconf (only needs to be run once, unless configure.ac is changed) ./configure --prefix= (or with no prefix given; defaults to /usr/local) @@ -27,11 +34,13 @@ No distribution packages are available. To install from source: If `` is /usr, the binary will be installed to /usr/games, the data into /usr/share/... -To install without root privileges, try one of these when running -`configure` above: +Example for installing without root privileges: ./configure --prefix=$HOME/.local - ./configure --prefix=$PWD/pkg + +for testing changes, try + + ./configure --prefix=$PWD/install_test The prefix(path) to the data directory will be built into the binary. @@ -45,6 +54,10 @@ To uninstall: (If DESTDIR was used with 'install', it must be also be used with 'uninstall'. +To remove all files generated by './configure' + + make distclean + ## Contributing See diff --git a/configure.ac b/configure.ac index ecb427d..b4adf59 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,7 @@ # The arguments given to AC_INIT can be accessed from variables, and used in # Makefile.in or other .in files. To see available variables, see config.status # (generated by ./configure) +AC_PREREQ(2.69) AC_INIT([Telluric Deckay], m4_esyscmd([grep version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n"]), [https://github.com/TelluricDeckay/telluricdeckay/issues], @@ -11,10 +12,55 @@ AC_INIT([Telluric Deckay], DATE=$(date) AC_SUBST(DATE) +if test "x$prefix" = xNONE; then + PREFIX=$ac_default_prefix +else + PREFIX=$prefix +fi + +# if --datadir was not given to ./configure, then $datadir will = the +# literal string "${datarootdir}" +if test "x$datadir" != x\$\{datarootdir\}; then + DATADIR=${datadir} +else + DATADIR=$PREFIX/share +fi +AC_SUBST(DATADIR) + +# if --docdir was not given to ./configure, then $docdir will = the +# literal string "${datarootdir}/doc" +if test "x$docdir" != x\$\{datarootdir\}\/doc\/\$\{PACKAGE_TARNAME\}; then + DOCDIR=${docdir} +else + DOCDIR=$DATADIR/doc +fi +AC_SUBST(DOCDIR) + + +# if --bindir was not given to ./configure, then $bindir will = the +# literal string "${exec_prefix}\bin" +if test "x$bindir" != x\$\{exec_prefix\}\/bin; then + BINDIR=${bindir} +else + BINDIR=$PREFIX/games +fi +AC_SUBST(BINDIR) + +if test "x$exec_prefix" != xNONE; then + AC_MSG_ERROR([the --exec-prefix option is not supported]) +fi + AC_CONFIG_FILES([Makefile - telluricdeckay.desktop - telluricdeckay.appdata.xml + $PACKAGE_TARNAME.desktop + $PACKAGE_TARNAME.appdata.xml src/config_h.rs]) # Creates the files above by reading their corresponding .in file AC_OUTPUT + +echo -e +echo installation prefix = $prefix +echo The binary will be installed to $BINDIR +echo datadir = $DATADIR +echo docdir = $DOCDIR +echo -e diff --git a/src/config.rs b/src/config.rs index 5363c32..70244f9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,6 +6,28 @@ use std::{ use structopt::StructOpt; use telluricdeckay::{cli_options, config_h}; +pub fn get_datadir_with_package_name() -> String { + format!("{}/{}", config_h::get_datadir(), env!("CARGO_PKG_NAME")) +} + +pub fn get_cardsdir() -> String { + if Path::new("./assets/cards").exists() { + return "./assets/cards".to_owned(); + } + format!("{}/{}", get_datadir_with_package_name(), "cards") +} + +pub fn get_localedir() -> String { + format!("{}/{}", config_h::get_datadir(), "locale") +} + +pub fn get_pixmapsdir() -> String { + if Path::new("./assets").exists() { + return "./assets".to_owned(); + } + format!("{}/{}", config_h::get_datadir(), "pixmaps") +} + fn get_homedir() -> io::Result { let homedir: String = match dirs::home_dir() { Some(homedir) => homedir.to_str().unwrap().into(), @@ -133,3 +155,24 @@ pub fn get() -> Data { } config_data } + +#[test] +fn access_ace_of_clubs() { + assert_eq!( + Path::new(&format!("{}/AC.svg", get_cardsdir())).exists(), + true + ); +} + +#[test] +fn access_pixmap() { + assert_eq!( + Path::new(&format!( + "{}/{}.png", + get_pixmapsdir(), + env!("CARGO_PKG_NAME") + )) + .exists(), + true + ); +} diff --git a/src/config_h.rs.in b/src/config_h.rs.in index 2e9aa65..f6bb3ef 100644 --- a/src/config_h.rs.in +++ b/src/config_h.rs.in @@ -1,25 +1,4 @@ - -use std::path::Path; - -fn get_datadir() -> &'static str { - "@prefix@/share/" -} - -pub fn get_assetsdir() -> String { - if Path::new("./assets/cards").exists() { - return ".".to_owned(); - } - format!("{}/{}", get_datadir(), "@PACKAGE_TARNAME@") -} - -pub fn get_localedir() -> String { - format!("{}/{}", get_datadir(), "locale") -} - -pub fn get_pixmapsdir() -> String { - if Path::new("./assets").exists() { - return "./assets".to_owned(); - } - format!("{}/{}", get_datadir(), "pixmaps") +pub fn get_datadir() -> &'static str { + "@DATADIR@" } diff --git a/src/gui/asset_manager.rs b/src/gui/asset_manager.rs index 89aadf1..249ee29 100644 --- a/src/gui/asset_manager.rs +++ b/src/gui/asset_manager.rs @@ -1,4 +1,4 @@ -use crate::config_h; +use crate::config; use iced::{window::Icon, Length, Svg}; use image::{io::Reader as ImageReader, ImageResult, RgbaImage}; use ionic_deckhandler::{Card, Rank, Suit}; @@ -6,7 +6,7 @@ use ionic_deckhandler::{Card, Rank, Suit}; // TODO: these assets can take time to load. Perhaps look at way to cache them. // Card display. fn card_img(card_name: &str) -> Svg { - Svg::from_path(format!("{}/assets/cards/{}", config_h::get_assetsdir(), card_name)) + Svg::from_path(format!("{}/{}", config::get_cardsdir(), card_name)) .width(Length::Units(50)) .height(Length::Units(50)) } @@ -245,7 +245,12 @@ fn get_rgba8img(filename: &str) -> ImageResult { } pub fn get_icon() -> Option { - get_rgba8img(&format!("{}/telluricdeckay.png", config_h::get_pixmapsdir())).map_or_else( + get_rgba8img(&format!( + "{}/{}.png", + config::get_pixmapsdir(), + env!("CARGO_PKG_NAME") + )) + .map_or_else( |e| { eprintln!("Could not load image: {:?}", e); None @@ -261,3 +266,8 @@ pub fn get_icon() -> Option { }, ) } + +#[test] +fn test_get_icon() { + assert_eq!(get_icon().is_some(), true); +} diff --git a/src/main.rs b/src/main.rs index c8d2f40..87f2322 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ mod config; -mod config_h; mod game; mod gui; mod player; @@ -16,7 +15,7 @@ use tr::tr_init; struct Translations; fn main() -> Result<(), Error> { - tr_init!(config_h::get_localedir()); + tr_init!(config::get_localedir()); let translations = Translations {}; let language_loader = gettext_language_loader!();