Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to build static library (on iOS) #1206

Merged
merged 8 commits into from
Mar 14, 2023
16 changes: 16 additions & 0 deletions src/main/java/com/gluonhq/substrate/SubstrateDispatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -510,4 +510,20 @@ public boolean nativeSharedLibrary() throws Exception {
config.setSharedLibrary(true);
return targetConfiguration.createSharedLib();
}

/**
* This method builds a static library that can be used by third
* party projects, considering it contains one or more entry points.
*
* Static entry points, callable from C, can be created with the {@code @CEntryPoint}
* annotation.
*
* @throws Exception
*/
public boolean nativeStaticLibrary() throws Exception {
Logger.logInfo(logTitle("STATIC LIBRARY TASK"));
config.setStaticLibrary(true);
return targetConfiguration.createStaticLib();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class InternalProjectConfiguration {
private boolean enableCheckHash = true;
private boolean usesJDK11 = false;
private boolean sharedLibrary = false;
private boolean staticLibrary = false;

private String backend;
private List<String> initBuildTimeList;
Expand Down Expand Up @@ -335,6 +336,14 @@ public void setSharedLibrary(boolean sharedLibrary) {
this.sharedLibrary = sharedLibrary;
}

public boolean isStaticLibrary() {
return staticLibrary;
}

public void setStaticLibrary(boolean staticLibrary) {
this.staticLibrary = staticLibrary;
}

public Triplet getTargetTriplet() {
return Objects.requireNonNull( publicConfig.getTargetTriplet(), "Target triplet is required");
}
Expand All @@ -360,6 +369,7 @@ public void setBackend(String backend) {
this.backend = backend;
}

@Deprecated
public boolean isUseLLVM() {
return Constants.BACKEND_LLVM.equals(backend);
}
Expand Down Expand Up @@ -511,6 +521,7 @@ public void checkGraalVMVendor() throws IOException {
* @throws IOException
* @throws InterruptedException
*/
@Deprecated
public void canRunLLVM(Triplet triplet) throws IOException, InterruptedException {
if (!new Triplet(Constants.Profile.IOS).equals(triplet) &&
!new Triplet(Constants.Profile.ANDROID).equals(triplet) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,32 +184,22 @@ public boolean compile() throws IOException, InterruptedException {
return validateCompileResult(result);
}

/**
* Links a previously created objectfile with the required
* dependencies into a native executable.
* @return true if linking succeeded, false otherwise
*/
@Override
public boolean link() throws IOException, InterruptedException {
compileAdditionalSources();
ensureClibs();

String appName = projectConfiguration.getAppName();
String objectFilename = projectConfiguration.getMainClassName().toLowerCase(Locale.ROOT) + "." + getObjectFileExtension();
Path gvmPath = paths.getGvmPath();
Path objectFile = FileOps.findFile(gvmPath, objectFilename).orElseThrow( () ->
new IllegalArgumentException(
"Linking failed, since there is no objectfile named " + objectFilename + " under " + gvmPath.toString())
);
Path objectFile = getProjectObjectFile();

if (projectConfiguration.isStaticLibrary()) {
return createStaticLib();
}
ProcessRunner linkRunner = new ProcessRunner(getLinker());

Path gvmAppPath = gvmPath.resolve(appName);
linkRunner.addArgs(getAdditionalSourceFiles().stream()
.map(s -> s.replaceAll("\\..*", "." + getObjectFileExtension()))
.distinct()
.map(sourceFile -> gvmAppPath.resolve(sourceFile).toString())
.collect(Collectors.toList()));
linkRunner.addArgs(getAdditionalObjectFiles());

linkRunner.addArg(objectFile.toString());
linkRunner.addArgs(getTargetSpecificObjectFiles());
Expand Down Expand Up @@ -317,6 +307,17 @@ public boolean createSharedLib() throws IOException, InterruptedException {
return true;
}

/**
* Creates a static library
* @return true if the process succeeded or false if the process failed
* @throws IOException
* @throws InterruptedException
*/
@Override
public boolean createStaticLib() throws IOException, InterruptedException {
return true;
}

// --- private methods

protected boolean compileAdditionalSources()
Expand Down Expand Up @@ -978,6 +979,7 @@ List<String> getTargetSpecificAOTCompileFlags() throws IOException {
return Collections.emptyList();
}

@Deprecated
jperedadnr marked this conversation as resolved.
Show resolved Hide resolved
List<String> getTargetSpecificObjectFiles() throws IOException {
return Collections.emptyList();
}
Expand Down Expand Up @@ -1030,4 +1032,38 @@ protected List<Path> getStaticJDKLibPaths() throws IOException {
return Arrays.asList(staticJDKLibPath);
}
}

/**
* Get the objectfiles that are compiled from the additionalSourceFiles
*
* @return
*/
final List<String> getAdditionalObjectFiles() {
String appName = projectConfiguration.getAppName();
Path gvmPath = paths.getGvmPath();
Path gvmAppPath = gvmPath.resolve(appName);
List<String> answer = getAdditionalSourceFiles().stream()
.map(s -> s.replaceAll("\\..*", "." + getObjectFileExtension()))
.distinct()
.map(sourceFile -> gvmAppPath.resolve(sourceFile).toString())
.collect(Collectors.toList());

return answer;
}

/**
* Return the location of the compiled application file. This is the file
* that is generated by the AOT compiler.
*
* @return the Path to the compiled application
*/
final Path getProjectObjectFile() throws IOException {
Path gvmPath = paths.getGvmPath();
String objectFilename = projectConfiguration.getMainClassName().toLowerCase(Locale.ROOT) + "." + getObjectFileExtension();
Path objectFile = FileOps.findFile(gvmPath, objectFilename).orElseThrow(()
-> new IllegalArgumentException(
"Linking failed, since there is no objectfile named " + objectFilename + " under " + gvmPath.toString())
);
return objectFile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ List<String> getTargetSpecificAOTCompileFlags() throws IOException {
return flags;
}

@Deprecated
@Override
List<String> getTargetSpecificObjectFiles() throws IOException {
if (projectConfiguration.isUseLLVM()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ List<String> copyAdditionalSourceFiles(Path workDir) throws IOException {
return files;
}

@Deprecated
@Override
List<String> getTargetSpecificObjectFiles() throws IOException {
if (isSimulator() || !projectConfiguration.isUseLLVM()) {
Expand Down Expand Up @@ -342,6 +343,20 @@ String getAppPath(String appName) {
return appPath.toString() + "/" + appName;
}

@Override
public boolean createStaticLib() throws IOException, InterruptedException {
ProcessRunner linkRunner = new ProcessRunner("ar");
linkRunner.addArg("rcs");
Path dest = paths.getGvmPath().resolve("lib"+projectConfiguration.getAppName()+".a");
linkRunner.addArg(dest.toString());
linkRunner.addArg(getProjectObjectFile().toString());
linkRunner.addArgs(getAdditionalObjectFiles());
linkRunner.setInfo(true);
linkRunner.setLogToFile(true);
int result = linkRunner.runProcess("archive");
return result == 0;
}

private String getTargetArch() {
return projectConfiguration.getTargetTriplet().getArch();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public interface TargetConfiguration {
*/
boolean compile() throws Exception;

/**
* Links a previously created objectfile with the required
* dependencies into a native executable or library
* @return true if linking succeeded, false otherwise
*/
boolean link() throws IOException, InterruptedException;

/**
Expand Down Expand Up @@ -91,4 +96,13 @@ public interface TargetConfiguration {
* @throws InterruptedException
*/
boolean createSharedLib() throws IOException, InterruptedException;

/**
* Creates a static library
* @return true if the process succeeded or false if the process failed
* @throws IOException
* @throws InterruptedException
*/
boolean createStaticLib() throws IOException, InterruptedException;

}