WIP. Posting just to make sure people know this is something I'd like to do. Context: https://matrix.to/#/!PvnunzXUk4Vm1CmKS4:auxolotl.org/$bOm6iaBpWbo-KRJgo7FUZdeFIv9StzRHxklbx7OQ23g?via=auxolotl.org&via=matrix.org&via=catgirl.cloud Reasons: 1. Why should GCC inflict complication upon all of tidepool just because of its own architectural deficiencies? 2. Most other compilers are multi-target so it doesn't matter 2. Target is useless for 99.9% of packages and only leads to user confusion, especially since many compilers also call what would be host here "target". 3. Canadian-cross is not very well supported. GCC barely supports it, and is broken in many cases. Nixpkgs does not support it (regardless of what its API may imply) and no one has ever complained. Plan: 1. Remove most target related things. No reason to have it. 2. Add configuration parameter on GCC that selects its target What does this mean: This basically moves target to be a GCC-specific artifact rather than an official parameter every package must endure the cognitive load of. This is because it is. Nixpkgs plans on dumping target in the future as well because of this. Or at least making it an alias. If you want to create a compiler with a different target, then override GCC to do so. No need to pervade all of tidepool just for GCC. Co-authored-by: Victor Fuentes <vlinkz@snowflakeos.org> Reviewed-on: #31 Reviewed-by: vlinkz <vlinkz@snowflakeos.org> Co-authored-by: Ross Smyth <snix@treefroog.com> Co-committed-by: Ross Smyth <snix@treefroog.com>
248 lines
7.4 KiB
Nix
248 lines
7.4 KiB
Nix
{ config }@global:
|
|
let
|
|
inherit (config) lib;
|
|
in
|
|
{
|
|
config = {
|
|
lib.packages = {
|
|
dependencies = {
|
|
get =
|
|
dependencies:
|
|
let
|
|
exists = value: !(builtins.isNull value);
|
|
available = builtins.filter exists dependencies;
|
|
in
|
|
builtins.map (dependency: dependency.package) available;
|
|
|
|
build =
|
|
build: host: builtins.mapAttrs (name: dep: (lib.packages.resolve dep).packages.${build}.${host});
|
|
|
|
collect =
|
|
package:
|
|
let
|
|
isPropagated = name: package: package.propagate or false;
|
|
getPropagatedDependencies = target: builtins.attrValues (lib.attrs.filter isPropagated target);
|
|
|
|
process =
|
|
dependencies:
|
|
let
|
|
getDeps =
|
|
name: dep:
|
|
let
|
|
dependency = lib.packages.resolve dep;
|
|
deps = {
|
|
build = getPropagatedDependencies dependency.deps.build ++ process dependency.deps.build;
|
|
host = getPropagatedDependencies dependency.deps.host ++ process dependency.deps.host;
|
|
};
|
|
in
|
|
lib.lists.flatten [
|
|
deps.build
|
|
deps.host
|
|
];
|
|
|
|
propagated = lib.attrs.mapToList getDeps dependencies;
|
|
in
|
|
lib.lists.flatten propagated;
|
|
|
|
withoutNulls = deps: builtins.filter (dep: dep != null) deps;
|
|
in
|
|
{
|
|
build = withoutNulls (builtins.attrValues package.deps.build ++ process package.deps.build);
|
|
host = withoutNulls (builtins.attrValues package.deps.host ++ process package.deps.host);
|
|
};
|
|
};
|
|
|
|
context = {
|
|
create =
|
|
package: collected: ctx:
|
|
let
|
|
process =
|
|
path: deps:
|
|
let
|
|
dependencies = lib.lists.flatten deps;
|
|
contexts = builtins.map (dependency: dependency.context or { }) dependencies;
|
|
result = lib.modules.run {
|
|
args = {
|
|
global = global.config;
|
|
};
|
|
|
|
prefix = package.__module__.args.dynamic.meta.prefix ++ [
|
|
"<context ${path}>"
|
|
];
|
|
|
|
modules = (builtins.map (context: { config = context; }) contexts) ++ [
|
|
{
|
|
freeform = lib.types.any;
|
|
|
|
options = config.packages.context.options // {
|
|
target = lib.options.create {
|
|
description = "The dependency target that is being generated.";
|
|
type = lib.types.enum [
|
|
"build"
|
|
"host"
|
|
];
|
|
writable = false;
|
|
default.value = path;
|
|
};
|
|
};
|
|
|
|
config = ctx;
|
|
}
|
|
];
|
|
};
|
|
in
|
|
result.config;
|
|
|
|
build = process "build" [
|
|
collected.build
|
|
];
|
|
host = process "host" [
|
|
collected.host
|
|
];
|
|
in
|
|
build
|
|
// host
|
|
// {
|
|
inherit
|
|
build
|
|
host
|
|
package
|
|
;
|
|
|
|
deps = collected;
|
|
|
|
__toString =
|
|
value:
|
|
let
|
|
all = builtins.mapAttrs (host: deps: builtins.map (dep: dep.package) deps) collected;
|
|
in
|
|
builtins.toJSON (
|
|
builtins.removeAttrs value [
|
|
"deps"
|
|
"__toString"
|
|
]
|
|
// {
|
|
deps = all;
|
|
}
|
|
);
|
|
};
|
|
};
|
|
|
|
hooks = {
|
|
create =
|
|
collected: ctx:
|
|
let
|
|
process =
|
|
path:
|
|
let
|
|
dependencies = lib.attrs.selectOrThrow path collected;
|
|
hooks = builtins.map (
|
|
dependency: if builtins.isFunction dependency.hooks then dependency.hooks ctx else dependency.hooks
|
|
) dependencies;
|
|
in
|
|
hooks;
|
|
in
|
|
{
|
|
build = process [
|
|
"build"
|
|
];
|
|
host = process [
|
|
"host"
|
|
];
|
|
};
|
|
};
|
|
|
|
getLatest =
|
|
alias:
|
|
let
|
|
versions = builtins.attrNames alias.versions;
|
|
sorted = builtins.sort (lib.versions.gte) versions;
|
|
in
|
|
builtins.head sorted;
|
|
|
|
getOutputs =
|
|
alias:
|
|
let
|
|
package = lib.packages.resolve alias;
|
|
outputs =
|
|
if builtins.isList package.outputs then
|
|
lib.attrs.generate package.outputs (output: package.package.${output})
|
|
else
|
|
package.outputs;
|
|
in
|
|
outputs;
|
|
|
|
WELL_KNOWN_ALIASES = [
|
|
# NOTE: When adding a version alias here, update lib.types.alias and lib.types.platforms' alias sub-option
|
|
"stable"
|
|
"latest"
|
|
];
|
|
|
|
resolve =
|
|
alias:
|
|
let
|
|
prefered = config.preferences.packages.version;
|
|
isWellKnown = builtins.elem prefered lib.packages.WELL_KNOWN_ALIASES;
|
|
in
|
|
if isWellKnown && alias ? ${prefered} then
|
|
alias.${prefered}
|
|
else if alias ? versions then
|
|
alias.versions.${prefered} or (alias.versions.${lib.packages.getLatest alias})
|
|
else
|
|
alias;
|
|
|
|
build =
|
|
alias: build: host:
|
|
let
|
|
package = lib.packages.resolve alias;
|
|
|
|
identifier = lib.options.getIdentifier [
|
|
"packages"
|
|
package.namespace
|
|
package.id
|
|
"versions"
|
|
package.version
|
|
];
|
|
|
|
buildSystem = lib.systems.withBuildInfo build;
|
|
hostSystem = lib.systems.withBuildInfo host;
|
|
|
|
platform = {
|
|
build = lib.modules.override 75 build;
|
|
host = lib.modules.override 75 host;
|
|
};
|
|
|
|
built = package.extendTemporarily {
|
|
inherit platform;
|
|
};
|
|
|
|
support = lib.packages.supports package buildSystem.double hostSystem.double;
|
|
|
|
result =
|
|
if !support.compatible then
|
|
builtins.throw "📦 [Aux Tidepool] Package `${identifier}` does not support the platform build=${buildSystem.double}, host=${hostSystem.double}"
|
|
else if support.broken then
|
|
builtins.throw "📦 [Aux Tidepool] Package `${identifier}` is marked as broken and cannot be built."
|
|
else
|
|
built;
|
|
in
|
|
builtins.addErrorContext "📦 [Aux Tidepool] while building package `${identifier}` for platform build=${buildSystem.double}, host=${hostSystem.double}" result;
|
|
|
|
supports =
|
|
alias: build: host:
|
|
let
|
|
package = lib.packages.resolve alias;
|
|
matches = builtins.filter (
|
|
platform: platform.build == build && platform.host == host
|
|
) package.platforms;
|
|
in
|
|
{
|
|
compatible =
|
|
(config.preferences.packages.allow.incompatible && builtins.length matches == 0)
|
|
|| builtins.length matches > 0;
|
|
|
|
broken = !config.preferences.packages.allow.broken && package.meta.broken;
|
|
};
|
|
};
|
|
};
|
|
}
|