test: a project and its pragma dependency load a shared sibling apart

The fixture app has `#pragma crafter dependency "../tool"` and loads
../shared for itself, which the tool loads too; the app is loaded with
no args, the case where the two cache keys used to match. With
CRAFTER_BUILD_MARCH=x86-64-v2, the app's copy of shared has to keep
that march and no -fPIC, and the tool's copy has to be host tooling.
Before the fix the app got the tool's copy back: one Configuration,
with march native and -fPIC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-31 05:10:28 +01:00
commit 95896a7ddd
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
7 changed files with 161 additions and 0 deletions

View file

@ -0,0 +1,22 @@
// SPDX-License-Identifier: LGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
import std;
import Crafter.Build;
#pragma crafter dependency "../tool"
using namespace Crafter;
// Loads for itself the sibling its tool loads, by the same path and, when
// the app gets no args, with the same args.
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
Configuration* shared = LocalProject({ .projectFile = "../shared/project.cpp" });
Configuration cfg;
cfg.path = "./";
cfg.name = "app";
cfg.outputName = "app";
cfg.type = ConfigurationType::Executable;
ApplyStandardArgs(cfg, args);
cfg.dependencies = { shared, ProjectDependency("tool") };
return cfg;
}

View file

@ -0,0 +1,5 @@
export module Shared;
import std;
export std::int32_t SharedValue() {
return 7;
}

View file

@ -0,0 +1,23 @@
// SPDX-License-Identifier: LGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
import std;
import Crafter.Build;
namespace fs = std::filesystem;
using namespace Crafter;
// The sibling both the tool and the app load. ApplyStandardArgs on purpose:
// it reads CRAFTER_BUILD_MARCH from the environment, which is how the test
// tells the app's copy from the one built as host tooling.
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
Configuration cfg;
cfg.path = "./";
cfg.name = "shared";
cfg.outputName = "shared";
cfg.type = ConfigurationType::LibraryStatic;
ApplyStandardArgs(cfg, args);
std::array<fs::path, 1> ifaces = { "interfaces/Shared" };
std::array<fs::path, 0> impls = {};
cfg.GetInterfacesAndImplementations(ifaces, impls);
return cfg;
}

View file

@ -0,0 +1,6 @@
export module Tool;
import std;
import Shared;
export std::int32_t ToolValue() {
return SharedValue();
}

View file

@ -0,0 +1,24 @@
// SPDX-License-Identifier: LGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
import std;
import Crafter.Build;
namespace fs = std::filesystem;
using namespace Crafter;
// The app's `#pragma crafter dependency`, with a sibling of its own.
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
Configuration* shared = LocalProject({ .projectFile = "../shared/project.cpp" });
Configuration cfg;
cfg.path = "./";
cfg.name = "tool";
cfg.outputName = "tool";
cfg.type = ConfigurationType::LibraryStatic;
ApplyStandardArgs(cfg, args);
cfg.dependencies = { shared };
std::array<fs::path, 1> ifaces = { "interfaces/Tool" };
std::array<fs::path, 0> impls = {};
cfg.GetInterfacesAndImplementations(ifaces, impls);
return cfg;
}