diff --git a/doc/build_instructions/nix.md b/doc/build_instructions/nix.md new file mode 100644 index 0000000000..46ff37b2d2 --- /dev/null +++ b/doc/build_instructions/nix.md @@ -0,0 +1,78 @@ +# Building and developing on Nix based systems + +The openage repository is a [nix flake](https://nixos.wiki/wiki/Flakes) that +allow Nix users to easily build, install and develop openage. + +To build openage using nix + +1. make sure you have nix with flakes enabled, either by permanent system + configuration or by using command line flags, as described on + [the wiki](https://nixos.wiki/wiki/Flakes); +2. clone this repository and `cd` into it; +3. run `nix build .#openage` to start the build process; +4. the built artifact will be in `./result`. + +Nix will configure and build the source code automatically via the +`configurePhase` and `buildPhase` scripts, automatically provided by nix. + +If you want to build the derivation and run it immediately, you can use + +``` +nix run .#openage +``` + +instead of + +``` +nix build .#openage +./result/bin/openage +``` + +## Development + +You can get a development shell, with the required dependencies, by running + +``` +nix shell +``` + +This will download the same dependencies used for build and pop you in a +shell ready for use. You can call `configurePhase` and `buildPhase` to run +cmake configuration and building. + +Please note that nyan is downloaded from github as defined in `nix/nyan.nix`, +so if you want to provide nyan source tree, you'll need to modify that file +to use a path (such as `../../nyan`, relative to `nyan.nix`) instead of the +`fetchFromGitHub` function, for example: + +``` +# Clone both +git clone https://github.com/SFTtech/nyan +git clone https://github.com/SFTtech/openage +``` + +Then edit `openage/nix/nyan.nix` to use `../../nyan`, the result will be like + +``` +$ head -n18 openage/nix/nyan.nix + +``` +{ lib +, stdenv +, fetchFromGitHub +, clang +, cmake +, flex +}: +let + pname = "nyan"; + version = "0.3"; +in +stdenv.mkDerivation +{ + inherit pname version; + + src = ../../nyan; + + nativeBuildInputs = [ +``` diff --git a/doc/building.md b/doc/building.md index e7e0339d64..619ad7a423 100644 --- a/doc/building.md +++ b/doc/building.md @@ -84,9 +84,9 @@ described below for some of the most common ones: - [Arch Linux](build_instructions/arch_linux.md) - [FreeBSD](build_instructions/freebsd.md) - [Gentoo](build_instructions/gentoo.md) +- [Nix/NixOS](build_instructions/nix.md) - [Microsoft Windows](build_instructions/windows_msvc.md) - ### nyan installation `openage` depends on [`nyan`](https://github.com/SFTtech/nyan), which is the diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..dae268d7dc --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1711460390, + "narHash": "sha256-akSgjDZL6pVHEfSE6sz1DNSXuYX6hq+P/1Z5IoYWs7E=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "44733514b72e732bd49f5511bd0203dea9b9a434", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..2e28a3b7dd --- /dev/null +++ b/flake.nix @@ -0,0 +1,39 @@ +{ + # This is a nix flake that contains a declarative definition of the openage + # and nyan packages, providing convenient and reproducible builds and + # development shells. + + description = "Free (as in freedom) open source clone of the Age of Empires II engine"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let pkgs = import nixpkgs { inherit system; }; in + { + # This output is to build the derivation with `nix build` as well as to + # get development shells using `nix develop`. + # These are the packages provided by this flake: nyan and openage. + packages = rec { + # `nix build .#nyan` to build this + nyan = pkgs.callPackage ./nix/nyan.nix { }; + # `nix build .#openage` to build this + openage = pkgs.callPackage ./nix/openage.nix { + # Nyan is not provided by nixpkgs, but it comes from this flake + inherit (self.packages.${system}) nyan; + }; + # If no path is specified, openage is the default + default = openage; + }; + + # This output is to run the application directly with `nix run` + # (or `nix run .#openage` if you want to be explicit) + apps = rec { + openage = flake-utils.lib.mkApp { drv = self.packages.${system}.openage; }; + default = openage; + }; + }); +} diff --git a/nix/nyan.nix b/nix/nyan.nix new file mode 100644 index 0000000000..18ccb74288 --- /dev/null +++ b/nix/nyan.nix @@ -0,0 +1,44 @@ +{ lib +, stdenv +, fetchFromGitHub +, clang +, cmake +, flex +}: +let + pname = "nyan"; + version = "0.3"; +in +stdenv.mkDerivation +{ + inherit pname version; + + src = fetchFromGitHub { + owner = "SFTtech"; + repo = pname; + rev = "v${version}"; + hash = "sha256-bjz4aSS5RO+QuLd7kyblTPNcuQFhYK7sW1csNXHL4Qs="; + }; + + nativeBuildInputs = [ + clang + cmake + ]; + + buildInputs = [ + flex + ]; + + meta = with lib; { + description = "A data description language"; + longDescription = '' + Nyan stores hierarchical objects with key-value pairs in a database with the key idea that changes in a parent affect all children. We created nyan because there existed no suitable language to properly represent the enormous complexity of storing the data for openage. + ''; + homepage = "https://openage.sft.mx"; + license = licenses.lgpl3Plus; + platforms = platforms.unix; + mainProgram = "nyancat"; + }; +} + + diff --git a/nix/openage.nix b/nix/openage.nix new file mode 100644 index 0000000000..c26e51253a --- /dev/null +++ b/nix/openage.nix @@ -0,0 +1,113 @@ +# This file contains the definition of a nix expression that builds openage. +# A similar one exists from nyan, the configuration language. +# +# The expression in this file is a function (to be called by callPackage) +# that returns a derivation. callPackage is used inside the flake.nix file. +# +# To be compliant with nixpkgs, the dependencies can be passed via function +# arguments, similarly to how python3 or nyan is used here. The available +# packages that can be used when building/developing can be found among nixpkgs +# (https://search.nixos.org/) -as done with python3- or passed from the flake +# as done with nyan in the flake.nix file. +{ pkgs +, lib +, stdenv +, fetchFromGitHub +, nyan +, python3 +, ... +}: +let + pname = "openage"; + version = "0.5.3"; + + # Python libraries needed at build and run time. This function creates a + # python3 package configured with some packages (similar to a python venv). + # The current python3 version is used, which is python3.11 at the moment of + # writing. + # If more packages are needed, they can be added here. The available packages + # are listed at + # https://search.nixos.org/packages?channel=unstable&query=python311Packages + # For example, to add python311Packages.pybind11 to the dependencies, we could + # add to this list ps.pybind11 + pyEnv = python3.withPackages (ps: [ + ps.mako + ps.pillow + ps.numpy + ps.lz4 + ps.pygments + ps.cython + ps.pylint + ps.toml + ]); +in +stdenv.mkDerivation { + inherit pname version; + + # This uses the current checked-out repository as source code + src = ../.; + + # This fetches the code on github: one would use this when submitting the + # package to nixpkgs. + # src = fetchFromGitHub { + # owner = "SFTtech"; + # repo = pname; + # rev = "v${version}"; + # hash = "sha256-/ag4U7nnZbvkInnLOZ6cB2VWUb+n/HgM1wpo1y/mUHQ="; + # }; + + # Dependencies that are used only at build time + nativeBuildInputs = [ + # This is needed for qt applications + pkgs.qt6.wrapQtAppsHook + pkgs.toml11 + ]; + + # Dependencies that are used at build and run time + buildInputs = with pkgs; [ + nyan + pyEnv + + gcc + clang + cmake + gnumake + qt6.full + + eigen + libepoxy + libogg + libpng + dejavu_fonts + ftgl + fontconfig + harfbuzz + opusfile + libopus + qt6.qtdeclarative + qt6.qtmultimedia + ]; + + # openage requires access to both python dependencies and openage bindings + # Since nix places the binary somewhere in the nix store (/nix/store/blah), + # it needs to know where to find the python environment build above. This + # is done by setting the PYTHONPATH: the first part contains the path to + # the environment, the second part contains the path to the openage library + # build with this code. + postInstall = '' + wrapProgram $out/bin/openage --set PYTHONPATH "${pyEnv}/${pyEnv.sitePackages}:$out/lib/python3.11/site-packages/" + ''; + + # Metadata + meta = with lib; { + description = "Free (as in freedom) open source clone of the Age of Empires II engine"; + longDescription = '' + openage: a volunteer project to create a free engine clone of the Genie Engine used by Age of Empires, Age of Empires II (HD) and Star Wars: Galactic Battlegrounds, comparable to projects like OpenMW, OpenRA, OpenSAGE, OpenTTD and OpenRCT2. + + openage uses the original game assets (such as sounds and graphics), but (for obvious reasons) doesn't ship them + ''; + homepage = "https://openage.sft.mx"; + license = licenses.lgpl3Plus; + platforms = platforms.unix; + }; +}