Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into sym-2.105
Browse files Browse the repository at this point in the history
  • Loading branch information
kinke committed Oct 25, 2023
2 parents adcfb47 + b9e70e1 commit a57ba54
Show file tree
Hide file tree
Showing 34 changed files with 524 additions and 632 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/d.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
os: [ubuntu-22.04, windows-2019]
# Remember to change the compiler versions further below as well as here
dc:
- dmd-2.105.0
- dmd-2.105.2
- ldc-1.34.0

runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -55,8 +55,8 @@ jobs:
matrix:
os: [ubuntu-22.04, macos-12, windows-2022]
dc:
- dmd-2.105.0
- ldc-1.33.0
- dmd-2.105.2
- ldc-1.34.0
runs-on: ${{ matrix.os }}
defaults:
run:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
bin
tmp
.dub
.reggae
*.ninja
compile_commands.json
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ luarocks to install the reggae package (reggae-js for npm). This is
not required; the reggae binary includes the API for all scripting
languages.

In D, a function with return type `Build` must exist with any name.
Normally this function isn't written by hand but by using the
[build template mixin](payload/reggae/build.d).
In D, a function called `reggaeBuild` must exist that returns a
`Build` object. Normally this function isn't written by hand but by
using the [build template mixin](payload/reggae/build.d).

From the the build directory, run `reggae [-b <ninja|make|tup|binary>]
/path/to/your/project`. You can now build your project using the
Expand Down
38 changes: 14 additions & 24 deletions payload/reggae/build.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
to be expressed in. $(D Build) is a container struct for top-level
targets, $(D Target) is the heart of the system.
*/

module reggae.build;

import reggae.ctaa;
Expand All @@ -29,8 +28,9 @@ import std.typecons;
*/
struct Build {
static struct TopLevelTarget {
import std.typecons: Flag;
Target target;
bool optional;
Flag!"optional" optional;
}

private TopLevelTarget[] _targets;
Expand Down Expand Up @@ -84,10 +84,12 @@ struct Build {
}

static Build fromBytes(ubyte[] bytes) @trusted {
import std.typecons: No;

immutable length = getUshort(bytes);
auto build = Build();
foreach(_; 0 .. length) {
build._targets ~= TopLevelTarget(Target.fromBytes(bytes), false);
build._targets ~= TopLevelTarget(Target.fromBytes(bytes), No.optional);
}
return build;
}
Expand All @@ -106,10 +108,14 @@ Build.TopLevelTarget optional(alias targetFunc)() {
Designate a target as optional so it won't be built by default.
*/
Build.TopLevelTarget optional(Target target) {
return createTopLevelTarget(target, true);
import std.typecons: Yes;
return createTopLevelTarget(target, Yes.optional);
}

Build.TopLevelTarget createTopLevelTarget(Target target, bool optional = false) {
Build.TopLevelTarget createTopLevelTarget(
Target target,
imported!"std.typecons".Flag!"optional" optional = imported!"std.typecons".No.optional)
{
return Build.TopLevelTarget(target.inTopLevelObjDirOf(objDirOf(target), Yes.topLevel), optional);
}

Expand Down Expand Up @@ -172,12 +178,6 @@ unittest {
static assert(isTarget!t3);
}

mixin template buildImpl(targets...) if(allSatisfy!(isTarget, targets)) {
Build buildFunc() {
return Build(targets);
}
}

/**
Two variations on a template mixin. When reggae is used as a library,
this will essentially build reggae itself as part of the build description.
Expand All @@ -198,22 +198,12 @@ version(reggaelib) {
alias build = buildImpl;
}

package template isBuildFunction(alias T) {
static if(!isSomeFunction!T) {
enum isBuildFunction = false;
} else {
enum isBuildFunction = is(ReturnType!T == Build) && arity!T == 0;
mixin template buildImpl(targets...) if(allSatisfy!(isTarget, targets)) {
Build reggaeBuild() {
return Build(targets);
}
}

unittest {
Build myBuildFunction() { return Build(); }
static assert(isBuildFunction!myBuildFunction);
float foo;
static assert(!isBuildFunction!foo);
}


private static auto arrayify(E, T)(T value) {
import std.array: array;

Expand Down
30 changes: 25 additions & 5 deletions payload/reggae/buildgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import reggae.build;
import reggae.options;
import reggae.types;
import reggae.backend;
import reggae.reflect;
import reggae.path: buildPath;

import std.stdio;
Expand Down Expand Up @@ -49,20 +48,27 @@ mixin template BuildGenMain(string buildModule = "reggaefile") {

void doBuildFor(alias module_ = "reggaefile")(in Options options, string[] args = []) {
auto build = getBuildObject!module_(options);
if(!options.noCompilationDB) writeCompilationDB(build, options);
doBuild(build, options, args);
}

Build getBuildObject(alias module_)(in Options options) {
alias buildFunc = getBuildFunc!module_;
static if(is(buildFunc == void))
throw new Exception("No `Build reggaeBuild()` function in " ~ module_);
else
return getBuildObjectImpl!module_(options);
}

// calls the build function or loads it from the cache and returns
// the Build object
Build getBuildObject(alias module_)(in Options options) {
private Build getBuildObjectImpl(alias module_)(in Options options) {
import std.file;

immutable cacheFileName = buildPath(".reggae", "cache");
if(!options.cacheBuildInfo ||
!cacheFileName.exists ||
thisExePath.timeLastModified > cacheFileName.timeLastModified) {
const buildFunc = getBuild!(module_); //get the function to call by CT reflection
alias buildFunc = getBuildFunc!module_;
auto build = buildFunc(); //actually call the function to get the build description

if(options.cacheBuildInfo) {
Expand All @@ -78,8 +84,22 @@ Build getBuildObject(alias module_)(in Options options) {
}
}

private template getBuildFunc(alias module_) {
static if(is(typeof(module_) == string)) {
mixin(`static import `, module_, `;`);
alias getBuildFunc = getBuildFunc!(mixin(module_));
} else { // it's a module, not a string
static if(__traits(hasMember, module_, "reggaeBuild"))
alias getBuildFunc = module_.reggaeBuild;
else
alias getBuildFunc = void;
}

}

// Exports / does the build (binary backend) / produces the build file(s) (make, ninja, tup)
void doBuild(Build build, in Options options, string[] args = []) {
if(!options.noCompilationDB) writeCompilationDB(build, options);
options.export_ ? exportBuild(build, options) : doOneBuild(build, options, args);
}

Expand Down Expand Up @@ -132,7 +152,7 @@ private void exportBuild(Build build, in Options options) {
}


void writeCompilationDB(Build build, in Options options) {
private void writeCompilationDB(Build build, in Options options) {
import std.file;
import std.conv;
import std.algorithm;
Expand Down
1 change: 0 additions & 1 deletion payload/reggae/core/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
module reggae.core;

public import reggae.build;
public import reggae.reflect;
public import reggae.buildgen;
public import reggae.types;
public import reggae.config;
Expand Down
18 changes: 14 additions & 4 deletions payload/reggae/dependencies.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ string[] makeDeps(in string fileName) @safe {
if(!fileName.exists) return [];

const text = readText(fileName);

// The file is going to be like this: `foo.o: foo.d`, but possibly
// with arbitrary backslashes to extend the line
return text
Expand All @@ -24,10 +25,19 @@ string[] makeDeps(in string fileName) @safe {
.filter!(a => a.extension.among(".d", ".di"))
.filter!(a => a.baseName != "object.d")
.filter!(a => !a.canFind(buildPath("src", "reggae", ""))) // ignore reggae files
.filter!(a => !a.canFind(buildPath("std", ""))) // ignore phobos
.filter!(a => !a.canFind(buildPath("core", ""))) // ignore druntime
.filter!(a => !a.canFind(buildPath("etc", ""))) // ignore druntime
.filter!(a => !a.canFind(buildPath("ldc", ""))) // ignore ldc modules
.filter!(a => !a.isStdLib)
.array[1..$] // ignore the object file *and* the source file
;
}

private bool isStdLib(in string path) @safe pure nothrow {
import std.path: dirSeparator;
import std.algorithm: canFind, any;
import std.range: only;

bool isIn(in string containing) {
return path.canFind(dirSeparator ~ containing ~ dirSeparator);
}

return only("std", "core", "etc", "ldc").any!isIn;
}
Loading

0 comments on commit a57ba54

Please sign in to comment.