Skip to content

Commit

Permalink
Merge pull request #42692 from Thevakumar-Luheerathan/fix-ballerina-l…
Browse files Browse the repository at this point in the history
…ang-iss-42358

Change run command implementation
  • Loading branch information
Thevakumar-Luheerathan committed May 10, 2024
2 parents 740a149 + 523fb9c commit a162323
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public void execute() {
// compile the modules
.addTask(new CompileTask(outStream, errStream, false, true,
isPackageModified, buildOptions.enableCache()))
.addTask(new CreateExecutableTask(outStream, this.output))
.addTask(new CreateExecutableTask(outStream, this.output, null, false))
.addTask(new DumpBuildTimeTask(outStream), !project.buildOptions().dumpBuildTime())
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ private TaskExecutor createTaskExecutor(boolean isPackageModified, String[] args
.addTask(new ResolveMavenDependenciesTask(outStream))
.addTask(new CompileTask(outStream, errStream, false, false, isPackageModified,
buildOptions.enableCache()))
.addTask(new CreateExecutableTask(outStream, null), false)
.addTask(new CreateExecutableTask(outStream, null, null, false), false)
.addTask(new DumpBuildTimeTask(outStream), false)
.addTask(new RunProfilerTask(errStream), false).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import io.ballerina.cli.TaskExecutor;
import io.ballerina.cli.task.CleanTargetDirTask;
import io.ballerina.cli.task.CompileTask;
import io.ballerina.cli.task.CreateExecutableTask;
import io.ballerina.cli.task.DumpBuildTimeTask;
import io.ballerina.cli.task.ResolveMavenDependenciesTask;
import io.ballerina.cli.task.RunBuildToolsTask;
Expand All @@ -31,21 +32,26 @@
import io.ballerina.projects.BuildOptions;
import io.ballerina.projects.Project;
import io.ballerina.projects.ProjectException;
import io.ballerina.projects.ProjectKind;
import io.ballerina.projects.directory.BuildProject;
import io.ballerina.projects.directory.SingleFileProject;
import io.ballerina.projects.internal.model.Target;
import io.ballerina.projects.util.ProjectConstants;
import io.ballerina.projects.util.ProjectUtils;
import picocli.CommandLine;

import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import static io.ballerina.cli.cmd.Constants.RUN_COMMAND;
import static io.ballerina.cli.launcher.LauncherUtils.createLauncherException;
import static io.ballerina.projects.util.ProjectUtils.isProjectUpdated;
import static io.ballerina.runtime.api.constants.RuntimeConstants.SYSTEM_PROP_BAL_DEBUG;

Expand Down Expand Up @@ -238,6 +244,19 @@ public void execute() {
CommandUtil.exitError(this.exitWhenFinish);
return;
}
Target target;
try {
if (project.kind().equals(ProjectKind.BUILD_PROJECT)) {
target = new Target(project.targetDir());
} else {
target = new Target(Files.createTempDirectory("ballerina-cache" + System.nanoTime()));
target.setOutputPath(target.getBinPath());
}
} catch (IOException e) {
throw createLauncherException("unable to resolve the target path:" + e.getMessage());
} catch (ProjectException e) {
throw createLauncherException("unable to create the executable:" + e.getMessage());
}

// Check package files are modified after last build
boolean isPackageModified = isProjectUpdated(project);
Expand All @@ -252,7 +271,8 @@ public void execute() {
.addTask(new CompileTask(outStream, errStream, false, false,
isPackageModified, buildOptions.enableCache()))
// .addTask(new CopyResourcesTask(), isSingleFileBuild)
.addTask(new RunExecutableTask(args, outStream, errStream))
.addTask(new CreateExecutableTask(outStream, null, target, true))
.addTask(new RunExecutableTask(args, outStream, errStream, target))
.addTask(new DumpBuildTimeTask(outStream), !project.buildOptions().dumpBuildTime())
.build();
taskExecutor.executeTasks(project);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,27 +52,32 @@ public class CreateExecutableTask implements Task {
private final transient PrintStream out;
private Path output;
private Path currentDir;
private Target target;
private final boolean isHideTaskOutput;

public CreateExecutableTask(PrintStream out, String output) {
public CreateExecutableTask(PrintStream out, String output, Target target, boolean isHideTaskOutput) {
this.out = out;
this.target = target;
this.isHideTaskOutput = isHideTaskOutput;
if (output != null) {
this.output = Paths.get(output);
}
}

@Override
public void execute(Project project) {
this.out.println();

if (!project.buildOptions().nativeImage()) {
this.out.println("Generating executable");
if (!isHideTaskOutput) {
this.out.println();
if (!project.buildOptions().nativeImage()) {
this.out.println("Generating executable");
}
}

this.currentDir = Paths.get(System.getProperty(USER_DIR));
Target target = getTarget(project);

if (target == null) {
target = getTarget(project);
}
Path executablePath = getExecutablePath(project, target);

try {
PackageCompilation pkgCompilation = project.currentPackage().getCompilation();
JBallerinaBackend jBallerinaBackend = JBallerinaBackend.from(pkgCompilation, JvmTarget.JAVA_17);
Expand Down Expand Up @@ -106,15 +111,15 @@ public void execute(Project project) {
}

// Print diagnostics found during emit executable
if (!emitResult.diagnostics().diagnostics().isEmpty()) {
if (!emitResult.diagnostics().diagnostics().isEmpty() && !isHideTaskOutput) {
emitResult.diagnostics().diagnostics().forEach(d -> out.println("\n" + d.toString()));
}

} catch (ProjectException e) {
throw createLauncherException(e.getMessage());
}

if (!project.buildOptions().nativeImage()) {
if (!project.buildOptions().nativeImage() && !isHideTaskOutput) {
Path relativePathToExecutable = currentDir.relativize(executablePath);

if (project.buildOptions().getTargetPath() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,19 @@

import io.ballerina.cli.launcher.RuntimePanicException;
import io.ballerina.cli.utils.BuildTime;
import io.ballerina.projects.JBallerinaBackend;
import io.ballerina.projects.JarLibrary;
import io.ballerina.projects.JarResolver;
import io.ballerina.projects.JvmTarget;
import io.ballerina.projects.Module;
import io.ballerina.projects.PackageCompilation;
import io.ballerina.projects.Project;
import io.ballerina.projects.ProjectException;
import io.ballerina.projects.internal.model.Target;
import org.wso2.ballerinalang.util.Lists;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

import static io.ballerina.cli.launcher.LauncherUtils.createLauncherException;
import static io.ballerina.cli.utils.DebugUtils.getDebugArgs;
import static io.ballerina.cli.utils.DebugUtils.isInDebugMode;
import static io.ballerina.runtime.api.constants.RuntimeConstants.MODULE_INIT_CLASS_NAME;
import static org.wso2.ballerinalang.compiler.util.ProjectDirConstants.USER_DIR;

/**
Expand All @@ -54,6 +45,7 @@ public class RunExecutableTask implements Task {
private final List<String> args;
private final transient PrintStream out;
private final transient PrintStream err;
private final Target target;

/**
* Create a task to run the executable. This requires {@link CreateExecutableTask} to be completed.
Expand All @@ -62,10 +54,11 @@ public class RunExecutableTask implements Task {
* @param out output stream
* @param err error stream
*/
public RunExecutableTask(String[] args, PrintStream out, PrintStream err) {
public RunExecutableTask(String[] args, PrintStream out, PrintStream err, Target target) {
this.args = Lists.of(args);
this.out = out;
this.err = err;
this.target = target;
}

@Override
Expand All @@ -80,7 +73,7 @@ public void execute(Project project) {
out.println();

try {
this.runGeneratedExecutable(project.currentPackage().getDefaultModule(), project);
this.runGeneratedExecutable(project);
} catch (ProjectException e) {
throw createLauncherException(e.getMessage());
}
Expand All @@ -89,28 +82,19 @@ public void execute(Project project) {
}
}

private void runGeneratedExecutable(Module executableModule, Project project) {
PackageCompilation packageCompilation = project.currentPackage().getCompilation();
JBallerinaBackend jBallerinaBackend = JBallerinaBackend.from(packageCompilation, JvmTarget.JAVA_17);
JarResolver jarResolver = jBallerinaBackend.jarResolver();

String initClassName = JarResolver.getQualifiedClassName(
executableModule.packageInstance().packageOrg().toString(),
executableModule.packageInstance().packageName().toString(),
executableModule.packageInstance().packageVersion().toString(),
MODULE_INIT_CLASS_NAME);
private void runGeneratedExecutable(Project project) {
try {
List<String> commands = new ArrayList<>();
commands.add(System.getProperty("java.command"));
commands.add("-XX:+HeapDumpOnOutOfMemoryError");
commands.add("-XX:HeapDumpPath=" + System.getProperty(USER_DIR));
// Sets classpath with executable thin jar and all dependency jar paths.
commands.add("-cp");
commands.add(getAllClassPaths(jarResolver));
if (isInDebugMode()) {
commands.add(getDebugArgs(err));
}
commands.add(initClassName);
commands.add("-XX:+HeapDumpOnOutOfMemoryError");
commands.add("-XX:HeapDumpPath=" + System.getProperty(USER_DIR));
// Sets classpath with executable thin jar and all dependency jar paths.
commands.add("-jar");
commands.add(this.target.getExecutablePath(project.currentPackage()).toAbsolutePath()
.normalize().toString());
commands.addAll(args);
ProcessBuilder pb = new ProcessBuilder(commands).inheritIO();
Process process = pb.start();
Expand All @@ -123,14 +107,5 @@ private void runGeneratedExecutable(Module executableModule, Project project) {
throw createLauncherException("Error occurred while running the executable ", e.getCause());
}
}

private String getAllClassPaths(JarResolver jarResolver) {

StringJoiner cp = new StringJoiner(File.pathSeparator);
jarResolver.getJarFilePathsRequiredForExecution().stream()
.map(JarLibrary::path).map(Path::toString)
.forEach(cp::add);
return cp.toString();
}
}

0 comments on commit a162323

Please sign in to comment.