use of com.facebook.buck.android.NdkLibrary in project buck by facebook.
the class Project method walkRuleAndAdd.
/**
* Walks the dependencies of a build rule and adds the appropriate DependentModules to the
* specified dependencies collection. All library dependencies will be added before any module
* dependencies. See {@code ProjectTest#testThatJarsAreListedBeforeModules()} for details on why
* this behavior is important.
*/
@SuppressWarnings("PMD.LooseCoupling")
private void walkRuleAndAdd(final BuildRule rule, final boolean isForTests, final LinkedHashSet<SerializableDependentModule> dependencies, @Nullable final BuildRule srcTarget) {
final Path basePathForRule = rule.getBuildTarget().getBasePath();
Set<BuildRule> targetsToWalk;
if (rule instanceof JavaTest) {
targetsToWalk = ((JavaTest) rule).getCompiledTestsLibrary().getDeps();
} else {
targetsToWalk = rule.getDeps();
}
new AbstractBreadthFirstTraversal<BuildRule>(targetsToWalk) {
private final LinkedHashSet<SerializableDependentModule> librariesToAdd = Sets.newLinkedHashSet();
private final LinkedHashSet<SerializableDependentModule> modulesToAdd = Sets.newLinkedHashSet();
@Override
public ImmutableSet<BuildRule> visit(BuildRule dep) {
// Hack: we don't want uber R.java to show up in the deps that IntelliJ sees.
if (dep.getBuildTarget().toString().endsWith("_uber_r_dot_java")) {
return ImmutableSet.of();
}
ImmutableSet<BuildRule> depsToVisit;
if (rule.getProperties().is(PACKAGING) || dep instanceof AndroidResource || dep == rule) {
depsToVisit = dep.getDeps();
} else if (dep.getProperties().is(LIBRARY) && dep instanceof ExportDependencies) {
depsToVisit = ((ExportDependencies) dep).getExportedDeps();
} else {
depsToVisit = ImmutableSet.of();
}
// should contain the union of :lib and :test's deps as dependent modules.
if (isForTests && depsToVisit.isEmpty() && dep.getBuildTarget().getBasePath().equals(basePathForRule) && !dep.equals(srcTarget)) {
depsToVisit = dep.getDeps();
}
SerializableDependentModule dependentModule;
if (androidAars.contains(dep)) {
AndroidPrebuiltAar aar = androidAars.getParentAar(dep);
dependentModule = SerializableDependentModule.newLibrary(aar.getBuildTarget(), getIntellijNameForAar(aar));
} else if (dep instanceof PrebuiltJar) {
libraryJars.add(dep);
String libraryName = getIntellijNameForRule(dep);
dependentModule = SerializableDependentModule.newLibrary(dep.getBuildTarget(), libraryName);
} else if (dep instanceof AndroidPrebuiltAar) {
androidAars.add((AndroidPrebuiltAar) dep);
String libraryName = getIntellijNameForAar(dep);
dependentModule = SerializableDependentModule.newLibrary(dep.getBuildTarget(), libraryName);
} else if ((dep instanceof CxxLibrary) || (dep instanceof NdkLibrary) || (dep instanceof JavaLibrary) || (dep instanceof AndroidResource)) {
String moduleName = getIntellijNameForRule(dep);
dependentModule = SerializableDependentModule.newModule(dep.getBuildTarget(), moduleName);
} else {
return depsToVisit;
}
if (librariesToAdd.contains(dependentModule) || modulesToAdd.contains(dependentModule)) {
return depsToVisit;
}
if (isForTests) {
dependentModule.scope = "TEST";
} else {
// If the dependentModule has already been added in the "TEST" scope, then it should be
// removed and then re-added using the current (compile) scope.
String currentScope = dependentModule.scope;
dependentModule.scope = "TEST";
if (dependencies.contains(dependentModule)) {
dependencies.remove(dependentModule);
}
dependentModule.scope = currentScope;
}
// dependencies collection once the traversal is complete in the onComplete() method.
if (dependentModule.isLibrary()) {
librariesToAdd.add(dependentModule);
} else {
modulesToAdd.add(dependentModule);
}
return depsToVisit;
}
@Override
protected void onComplete() {
dependencies.addAll(librariesToAdd);
dependencies.addAll(modulesToAdd);
}
}.start();
}
use of com.facebook.buck.android.NdkLibrary in project buck by facebook.
the class ProjectTest method testNdkLibraryHasCorrectPath.
@Test
public void testNdkLibraryHasCorrectPath() throws Exception {
BuildRuleResolver ruleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
// Build up a the graph that corresponds to:
//
// ndk_library(
// name = 'foo-jni'
// )
//
// project_config(
// src_target = ':foo-jni',
// )
ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
BuildTarget fooJni = BuildTargetFactory.newInstance("//third_party/java/foo/jni:foo-jni");
NdkLibrary ndkLibrary = new NdkLibraryBuilder(fooJni).build(ruleResolver, projectFilesystem);
ProjectConfig ndkProjectConfig = ProjectConfigBuilder.createBuilder(BuildTargetFactory.newInstance("//third_party/java/foo/jni:project_config")).setSrcRule(ndkLibrary.getBuildTarget()).build(ruleResolver);
ProjectWithModules projectWithModules = getModulesForActionGraph(ruleResolver, ImmutableSortedSet.of(ndkProjectConfig), null, /* javaPackageFinder */
null);
List<SerializableModule> modules = projectWithModules.modules;
assertEquals("Should be one module for the ndk_library.", 1, modules.size());
SerializableModule androidLibraryModule = Iterables.getOnlyElement(modules);
assertListEquals(ImmutableList.of(SerializableDependentModule.newSourceFolder(), SerializableDependentModule.newInheritedJdk()), androidLibraryModule.getDependencies());
assertEquals(Paths.get(String.format("../../../../%s", ndkLibrary.getLibraryPath())), androidLibraryModule.nativeLibs);
}
use of com.facebook.buck.android.NdkLibrary in project buck by facebook.
the class Project method createModuleForProjectConfig.
@SuppressWarnings("PMD.LooseCoupling")
private SerializableModule createModuleForProjectConfig(ProjectConfig projectConfig, Optional<Path> rJava) throws IOException {
BuildRule projectRule = Preconditions.checkNotNull(projectConfig.getProjectRule());
Preconditions.checkState(projectRule instanceof AndroidBinary || projectRule instanceof AndroidLibrary || projectRule instanceof AndroidResource || projectRule instanceof JavaBinary || projectRule instanceof JavaLibrary || projectRule instanceof JavaTest || projectRule instanceof CxxLibrary || projectRule instanceof NdkLibrary, "project_config() does not know how to process a src_target of type %s (%s).", projectRule.getType(), projectRule.getBuildTarget());
LinkedHashSet<SerializableDependentModule> dependencies = Sets.newLinkedHashSet();
final BuildTarget target = projectConfig.getBuildTarget();
SerializableModule module = new SerializableModule(projectRule, target);
module.name = getIntellijNameForRule(projectRule);
module.isIntelliJPlugin = projectConfig.getIsIntelliJPlugin();
Path relativePath = projectConfig.getBuildTarget().getBasePath();
module.pathToImlFile = relativePath.resolve(module.name + ".iml");
// List the module source as the first dependency.
boolean includeSourceFolder = true;
// Do the tests before the sources so they appear earlier in the classpath. When tests are run,
// their classpath entries may be deliberately shadowing production classpath entries.
// tests folder
boolean hasSourceFoldersForTestRule = addSourceFolders(module, projectConfig.getTestRule(), projectConfig.getTestsSourceRoots(), true);
// test dependencies
BuildRule testRule = projectConfig.getTestRule();
if (testRule != null) {
walkRuleAndAdd(testRule, true, /* isForTests */
dependencies, projectConfig.getSrcRule());
}
// src folder
boolean hasSourceFoldersForSrcRule = addSourceFolders(module, projectConfig.getSrcRule(), projectConfig.getSourceRoots(), false);
addRootExcludes(module, projectConfig.getSrcRule(), projectFilesystem);
// non-library Android project with no source roots specified.
if (!hasSourceFoldersForTestRule && !hasSourceFoldersForSrcRule) {
includeSourceFolder = false;
}
// IntelliJ expects all Android projects to have a gen/ folder, even if there is no src/
// directory specified.
boolean isAndroidRule = projectRule.getProperties().is(ANDROID);
if (isAndroidRule) {
boolean hasSourceFolders = !module.sourceFolders.isEmpty();
module.sourceFolders.add(SerializableModule.SourceFolder.GEN);
if (!hasSourceFolders) {
includeSourceFolder = true;
}
}
// src dependencies
// Note that isForTests is false even if projectRule is the project_config's test_target.
walkRuleAndAdd(projectRule, false, /* isForTests */
dependencies, projectConfig.getSrcRule());
Path basePath = projectConfig.getBuildTarget().getBasePath();
// Specify another path for intellij to generate gen/ for each android module,
// so that it will not disturb our glob() rules.
// To specify the location of gen, Intellij requires the relative path from
// the base path of current build target.
module.moduleGenPath = generateRelativeGenPath(projectFilesystem, basePath);
if (turnOffAutoSourceGeneration && rJava.isPresent()) {
module.moduleRJavaPath = basePath.relativize(Paths.get("")).resolve(rJava.get());
}
SerializableDependentModule jdkDependency;
if (isAndroidRule) {
// android details
if (projectRule instanceof NdkLibrary) {
NdkLibrary ndkLibrary = (NdkLibrary) projectRule;
module.isAndroidLibraryProject = true;
module.keystorePath = null;
module.nativeLibs = relativePath.relativize(ndkLibrary.getLibraryPath());
} else if (projectRule instanceof AndroidLibrary) {
module.isAndroidLibraryProject = true;
module.keystorePath = null;
module.resFolder = intellijConfig.getAndroidResources().orElse(null);
module.assetFolder = intellijConfig.getAndroidAssets().orElse(null);
} else if (projectRule instanceof AndroidResource) {
AndroidResource androidResource = (AndroidResource) projectRule;
module.resFolder = createRelativeResourcesPath(Optional.ofNullable(androidResource.getRes()).map(resolver::getAbsolutePath).map(projectFilesystem::relativize).orElse(null), target);
module.isAndroidLibraryProject = true;
module.keystorePath = null;
} else if (projectRule instanceof AndroidBinary) {
AndroidBinary androidBinary = (AndroidBinary) projectRule;
module.resFolder = intellijConfig.getAndroidResources().orElse(null);
module.assetFolder = intellijConfig.getAndroidAssets().orElse(null);
module.isAndroidLibraryProject = false;
module.binaryPath = generateRelativeAPKPath(projectFilesystem, projectRule.getBuildTarget().getShortName(), basePath);
KeystoreProperties keystoreProperties = KeystoreProperties.createFromPropertiesFile(resolver.getAbsolutePath(androidBinary.getKeystore().getPathToStore()), resolver.getRelativePath(androidBinary.getKeystore().getPathToPropertiesFile()), projectFilesystem);
// getKeystore() returns an absolute path, but an IntelliJ module
// expects the path to the keystore to be relative to the module root.
// First, grab the aboslute path to the project config.
BuildTarget projectTarget = projectConfig.getBuildTarget();
Path modulePath = projectTarget.getCellPath().resolve(projectTarget.getBasePath());
// Now relativize to the keystore path, which is absolute too.
module.keystorePath = modulePath.relativize(keystoreProperties.getKeystore());
} else {
module.isAndroidLibraryProject = true;
module.keystorePath = null;
}
module.hasAndroidFacet = true;
module.proguardConfigPath = null;
module.androidManifest = resolveAndroidManifestRelativePath(basePath);
// List this last so that classes from modules can shadow classes in the JDK.
jdkDependency = SerializableDependentModule.newInheritedJdk();
} else {
module.hasAndroidFacet = false;
if (module.isIntelliJPlugin()) {
jdkDependency = SerializableDependentModule.newIntelliJPluginJdk();
} else {
jdkDependency = SerializableDependentModule.newStandardJdk(intellijConfig.getJdkName(), intellijConfig.getJdkType());
}
}
// Assign the dependencies.
module.setModuleDependencies(createDependenciesInOrder(includeSourceFolder, dependencies, jdkDependency));
// Annotation processing generates sources for IntelliJ to consume, but does so outside
// the module directory to avoid messing up globbing.
JavaLibrary javaLibrary = null;
if (projectRule instanceof JavaLibrary) {
javaLibrary = (JavaLibrary) projectRule;
}
if (javaLibrary != null) {
Optional<Path> processingParams = javaLibrary.getGeneratedSourcePath();
if (processingParams.isPresent()) {
module.annotationGenPath = basePath.relativize(processingParams.get());
module.annotationGenIsForTest = !hasSourceFoldersForSrcRule;
}
}
return module;
}
Aggregations