Skip to content

Commit

Permalink
API for conventional archive and executable file names (#50)
Browse files Browse the repository at this point in the history
* Don't apply cpp plugin

* Require JDK 17

* Shorten notation of test files.

* API for conventional archive and executable file names.

Closes #33.
  • Loading branch information
pedrolamarao authored Oct 10, 2023
1 parent 65df908 commit 3f799f8
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 31 deletions.
6 changes: 6 additions & 0 deletions plugins/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ plugins {
id("jvm-test-suite")
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

gradlePlugin {
website = "https://github.com/pedrolamarao/gradle-metal"
vcsUrl = "https://github.com/pedrolamarao/gradle-metal.git"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void apply () throws IOException
metal {
applications {
named("main") {
main {
linkOptions = listOf()
}
}
Expand All @@ -36,7 +36,6 @@ public void apply () throws IOException
GradleRunner.create()
.withPluginClasspath()
.withProjectDir(projectDir.toFile())
.withDebug(true)
.build();
}

Expand All @@ -53,12 +52,12 @@ public void language (String language) throws IOException
metal {
%s {
named("main") {
main {
compileOptions = listOf()
}
}
applications {
named("main") {
main {
archiveOptions = listOf()
}
}
Expand All @@ -69,7 +68,6 @@ public void language (String language) throws IOException
GradleRunner.create()
.withPluginClasspath()
.withProjectDir(projectDir.toFile())
.withDebug(true)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void apply () throws IOException
metal {
archives {
named("main") {
main {
archiveOptions = listOf()
}
}
Expand All @@ -36,7 +36,6 @@ public void apply () throws IOException
GradleRunner.create()
.withPluginClasspath()
.withProjectDir(projectDir.toFile())
.withDebug(true)
.build();
}

Expand All @@ -53,12 +52,12 @@ public void language (String language) throws IOException
metal {
%s {
named("main") {
main {
compileOptions = listOf()
}
}
archives {
named("main") {
main {
archiveOptions = listOf()
}
}
Expand All @@ -69,7 +68,6 @@ public void language (String language) throws IOException
GradleRunner.create()
.withPluginClasspath()
.withProjectDir(projectDir.toFile())
.withDebug(true)
.build();
}

Expand Down Expand Up @@ -101,8 +99,7 @@ int main (int argc, char * argv[])
GradleRunner.create()
.withPluginClasspath()
.withProjectDir(projectDir.toFile())
.withDebug(true)
.withArguments("link-test")
.withArguments("run-test")
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public class MetalAsmPlugin implements Plugin<Project>
public void apply (Project project)
{
project.getPluginManager().apply(MetalBasePlugin.class);
project.getPluginManager().apply(MetalCppPlugin.class);

final var metal = project.getExtensions().getByType(MetalExtension.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public Provider<RegularFile> getOutput ()
{
return getOutputDirectory().map(out -> {
final var target = getTarget().get();
final var name = getProject().getName();
return out.file("%s/%s.lib".formatted(target,name));
final var file = getMetal().get().archiveFileName(target,getProject().getName());
return out.file("%s/%s".formatted(target,file));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
@NonNullApi
public abstract class MetalExtension implements ExtensionAware
{
// properties

/**
* Metal service.
*
Expand Down Expand Up @@ -46,7 +48,7 @@ public abstract class MetalExtension implements ExtensionAware
*/
public Provider<String> getHostTarget ()
{
return getMetalService().flatMap(MetalService::getHostTarget);
return getMetalService().map(MetalService::getHost);
}

/**
Expand All @@ -56,6 +58,30 @@ public Provider<String> getHostTarget ()
*/
public abstract ListProperty<String> getLinkOptions ();

// methods

/**
* Formats an archive file name according to the host conventions.
*
* @param name core name
* @return file name
*/
public Provider<String> archiveFileName (String name)
{
return getMetalService().map(it -> it.archiveFileName(name));
}

/**
* Formats an executable file name according to the host conventions.
*
* @param name core name
* @return file name
*/
public Provider<String> executableFileName (String name)
{
return getMetalService().map(it -> it.executableFileName(name));
}

/**
* Locate tool.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public Provider<RegularFile> getOutput ()
{
return getOutputDirectory().map(out -> {
final var target = getTarget().get();
final var name = getProject().getName();
return out.file("%s/%s.exe".formatted(target,name));
final var file = getMetal().get().executableFileName(target,getProject().getName());
return out.file("%s/%s".formatted(target,file));
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,47 @@
package br.dev.pedrolamarao.gradle.metal.base;

import org.gradle.api.GradleException;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.ProviderFactory;
import org.gradle.api.services.BuildService;
import org.gradle.api.services.BuildServiceParameters;
import org.gradle.process.ExecOperations;

import javax.inject.Inject;
import java.io.File;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;

/**
* Metal service.
*/
public abstract class MetalService implements BuildService<BuildServiceParameters.None>
{
private final Provider<String> hostTarget;
private final AtomicReference<String> hostTarget = new AtomicReference<>();

private final Provider<String> path;
private final String path;

/**
* Constructor.
*/
@Inject
public MetalService ()
{
hostTarget = getProviders().of(MetalHostTargetSource.class, it -> {});
path = getProviders().gradleProperty("metal.path")
.orElse(getProviders().environmentVariable("PATH"));
.orElse(getProviders().environmentVariable("PATH"))
.orElse("")
.get();
}

/**
* Exec operations service.
*
* @return service
*/
@Inject
protected abstract ExecOperations getExec ();

/**
* Provider factory service.
*
Expand All @@ -39,11 +53,117 @@ public MetalService ()
/**
* Host target.
*
* @return provider
* @return target name
*/
public String getHost ()
{
final var cached = hostTarget.get();
if (cached != null) return cached;

final var buffer = new ByteArrayOutputStream();
getExec().exec(exec -> {
exec.executable( Metal.toExecutableFile(path,"clang") );
exec.args("-v");
exec.setErrorOutput(buffer);
});

String value = null;
try (var reader = new BufferedReader( new StringReader( buffer.toString() ) ) )
{
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("Target")) {
final var split = line.split(":");
if (split.length != 2) continue;
value = split[1].trim();
break;
}
}
}
catch (IOException e) { throw new GradleException("failed parsing clang -v output", e); }

if (value != null) {
hostTarget.set(value);
return value;
}

throw new GradleException("failed to discover host target");
}

/**
* Formats an archive file name according to the host convention.
*
* @param name core name
* @return file name
*/
public String archiveFileName (String name)
{
return archiveFileName(getHost(),name);
}

/**
* Formats an archive file name according to the target convention.
*
* @param target target
* @param name core name
* @return file name
*/
public String archiveFileName (String target, String name)
{
final var prefix = archiveFilePrefix(target);
final var suffix = archiveFileSuffix(target);
return "%s%s%s".formatted(prefix,name,suffix);
}

String archiveFilePrefix (String target)
{
final var parts = target.split("-");
if (contains(parts,"msvc")) return "";
else return "lib";
}

String archiveFileSuffix (String target)
{
final var parts = target.split("-");
if (contains(parts,"msvc")) return ".lib";
else return ".a";
}

/**
* Formats an executable file name according to the host convention.
*
* @param name core name
* @return file name
*/
public Provider<String> getHostTarget ()
public String executableFileName (String name)
{
return hostTarget;
return executableFileName(getHost(),name);
}

/**
* Formats an executable file name according to the target convention.
*
* @param target target
* @param name core name
* @return file name
*/
public String executableFileName (String target, String name)
{
final var prefix = executableFilePrefix(target);
final var suffix = executableFileSuffix(target);
return "%s%s%s".formatted(prefix,name,suffix);
}

String executableFilePrefix (String target)
{
return "";
}

String executableFileSuffix (String target)
{
final var parts = target.split("-");
if (contains(parts,"windows")) return ".exe";
else return "";
}

/**
Expand All @@ -54,6 +174,24 @@ public Provider<String> getHostTarget ()
*/
public Provider<File> locateTool (String name)
{
return path.map(it -> Metal.toExecutableFile(it,name));
for (var item : path.split(File.pathSeparator))
{
final var directory = Paths.get(item);
if (! Files.isDirectory(directory)) continue;
final var file = directory.resolve(name);
if (Files.isExecutable(file)) return getProviders().provider(file::toFile);
final var file_exe = file.resolveSibling(name + ".exe");
if (Files.isExecutable(file_exe)) return getProviders().provider(file_exe::toFile);
}

throw new GradleException("executable file not found: " + name);
}

static <T> boolean contains (T[] array, T value)
{
for (T item : array)
if (item.equals(value))
return true;
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ public abstract class MetalSourceTask extends SourceTask
*/
protected MetalSourceTask ()
{
getTarget().convention( getProviders().gradleProperty("metal.target").orElse( getMetal().flatMap(MetalService::getHostTarget) ) );
getTarget().convention( getProviders().gradleProperty("metal.target").orElse( getMetal().map(MetalService::getHost) ) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public class MetalCPlugin implements Plugin<Project>
public void apply (Project project)
{
project.getPluginManager().apply(MetalBasePlugin.class);
project.getPluginManager().apply(MetalCppPlugin.class);

final var metal = project.getExtensions().getByType(MetalExtension.class);

Expand Down
Loading

0 comments on commit 3f799f8

Please sign in to comment.