diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/BuildCommand.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/BuildCommand.java index 49095b8f5cb5..77c84410c35c 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/BuildCommand.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/BuildCommand.java @@ -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(); diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/ProfileCommand.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/ProfileCommand.java index 61060192d4ba..9671f211a027 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/ProfileCommand.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/ProfileCommand.java @@ -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(); } diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/RunCommand.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/RunCommand.java index 850573b0647c..3b5b93ca8687 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/RunCommand.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/RunCommand.java @@ -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; @@ -31,14 +32,18 @@ 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; @@ -46,6 +51,7 @@ 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; @@ -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); @@ -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); diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/CreateExecutableTask.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/CreateExecutableTask.java index 837921a87bed..c84b0c1e1e0c 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/CreateExecutableTask.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/CreateExecutableTask.java @@ -52,9 +52,13 @@ 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); } @@ -62,17 +66,18 @@ public CreateExecutableTask(PrintStream out, String 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); @@ -106,7 +111,7 @@ 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())); } @@ -114,7 +119,7 @@ public void execute(Project project) { throw createLauncherException(e.getMessage()); } - if (!project.buildOptions().nativeImage()) { + if (!project.buildOptions().nativeImage() && !isHideTaskOutput) { Path relativePathToExecutable = currentDir.relativize(executablePath); if (project.buildOptions().getTargetPath() != null) { diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunExecutableTask.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunExecutableTask.java index cb7f862c306a..8030f13f2844 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunExecutableTask.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunExecutableTask.java @@ -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; /** @@ -54,6 +45,7 @@ public class RunExecutableTask implements Task { private final List 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. @@ -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 @@ -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()); } @@ -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 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(); @@ -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(); - } }