Skip to content

Commit

Permalink
Allow to build static library (on iOS) (#1206)
Browse files Browse the repository at this point in the history
* Add required code so that plugins can request to build a static library.
This is currently a no-op.
Having this PR integrated allows the plugins to add the static lib option
as well.

Fix #1203

* move javadoc to superclass and add explicit reference that linking can also be used to link to a library

* add link to static archive for iOS

* Add static link procedure to create a static library on iOS.

* Process reviewer comments
  • Loading branch information
johanvos authored Mar 14, 2023
1 parent 37ea3cc commit e377ffb
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 15 deletions.
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
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;

}

0 comments on commit e377ffb

Please sign in to comment.