org.gradle.language.swift.tasks.SwiftCompile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.language.swift.tasks;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.Incubating;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.CacheableTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SkipWhenEmpty;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.WorkResult;
import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
import org.gradle.api.tasks.incremental.InputFileDetails;
import org.gradle.internal.Cast;
import org.gradle.internal.operations.logging.BuildOperationLogger;
import org.gradle.internal.operations.logging.BuildOperationLoggerFactory;
import org.gradle.language.base.compile.CompilerVersion;
import org.gradle.language.base.internal.compile.Compiler;
import org.gradle.language.base.internal.compile.VersionAwareCompiler;
import org.gradle.language.swift.SwiftVersion;
import org.gradle.language.swift.tasks.internal.DefaultSwiftCompileSpec;
import org.gradle.nativeplatform.internal.BuildOperationLoggingCompilerDecorator;
import org.gradle.nativeplatform.internal.CompilerOutputFileNamingSchemeFactory;
import org.gradle.nativeplatform.platform.NativePlatform;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.internal.NativeToolChainInternal;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.compilespec.SwiftCompileSpec;
import org.gradle.nativeplatform.toolchain.internal.swift.IncrementalSwiftCompiler;
import javax.inject.Inject;
import java.io.File;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Compiles Swift source files into object files.
*
* @since 4.1
*/
@Incubating
@CacheableTask
public class SwiftCompile extends DefaultTask {
private final Property moduleName;
private final RegularFileProperty moduleFile;
private final ConfigurableFileCollection modules;
private final ListProperty compilerArgs;
private final DirectoryProperty objectFileDir;
private final ConfigurableFileCollection source;
private final Property sourceCompatibility;
private final ListProperty macros;
private final Property debuggable;
private final Property optimize;
private final Property targetPlatform;
private final Property toolChain;
private final CompilerOutputFileNamingSchemeFactory compilerOutputFileNamingSchemeFactory;
@Inject
public SwiftCompile(CompilerOutputFileNamingSchemeFactory compilerOutputFileNamingSchemeFactory) {
this.compilerOutputFileNamingSchemeFactory = compilerOutputFileNamingSchemeFactory;
ObjectFactory objectFactory = getProject().getObjects();
this.moduleName = objectFactory.property(String.class);
this.moduleFile = objectFactory.fileProperty();
this.modules = getProject().files();
this.compilerArgs = objectFactory.listProperty(String.class);
this.objectFileDir = objectFactory.directoryProperty();
this.source = getProject().files();
this.sourceCompatibility = objectFactory.property(SwiftVersion.class);
this.macros = objectFactory.listProperty(String.class);
this.debuggable = objectFactory.property(Boolean.class).value(false);
this.optimize = objectFactory.property(Boolean.class).value(false);
this.targetPlatform = objectFactory.property(NativePlatform.class);
this.toolChain = objectFactory.property(NativeToolChain.class);
}
/**
* The tool chain used for compilation.
*
* @since 4.7
*/
@Internal
public Property getToolChain() {
return toolChain;
}
/**
* The platform being compiled for.
*
* @since 4.7
*/
@Nested
public Property getTargetPlatform() {
return targetPlatform;
}
/**
* Returns the source files to be compiled.
*
* @since 4.4
*/
@InputFiles
@SkipWhenEmpty
@PathSensitive(PathSensitivity.RELATIVE)
public ConfigurableFileCollection getSource() {
return source;
}
/**
* Macros that should be defined for the compiler.
*
* Macros do not have values in Swift; they are either present or absent.
*
* @since 4.7
*/
@Input
public ListProperty getMacros() {
return macros;
}
/**
* Should the compiler generate debuggable code?
*
* @since 4.7
*/
@Internal
public boolean isDebuggable() {
return debuggable.get();
}
/**
* Should the compiler generate debuggable code?
*
* @since 4.7
*/
@Input
public Property getDebuggable() {
return debuggable;
}
/**
* Should the compiler generate debuggable code?
*
* @since 4.7
*/
@Internal
public boolean isOptimized() {
return optimize.get();
}
/**
* Should the compiler generate optimized code?
*
* @since 4.7
*/
@Input
public Property getOptimized() {
return optimize;
}
/**
* Additional arguments to provide to the compiler.
*
* @since 4.4
*/
@Input
public ListProperty getCompilerArgs() {
return compilerArgs;
}
/**
* The directory where object files will be generated.
*
* @since 4.4
*/
@OutputDirectory
public DirectoryProperty getObjectFileDir() {
return objectFileDir;
}
/**
* The location to write the Swift module file to.
*
* @since 4.4
*/
@OutputFile
public RegularFileProperty getModuleFile() {
return moduleFile;
}
/**
* The name of the module to produce.
*/
@Optional
@Input
public Property getModuleName() {
return moduleName;
}
/**
* The modules required to compile the source.
*
* @since 4.4
*/
@InputFiles
@PathSensitive(PathSensitivity.NAME_ONLY)
public ConfigurableFileCollection getModules() {
return modules;
}
/**
* Returns the Swift language level to use to compile the source files.
*
* @since 4.6
*/
@Input
public Property getSourceCompatibility() {
return sourceCompatibility;
}
/**
* The compiler used, including the type and the version.
*
* @since 4.4
*/
@Nested
protected CompilerVersion getCompilerVersion() {
return ((VersionAwareCompiler)createCompiler()).getVersion();
}
private Compiler createCompiler() {
NativePlatformInternal targetPlatform = Cast.cast(NativePlatformInternal.class, this.targetPlatform.get());
NativeToolChainInternal toolChain = Cast.cast(NativeToolChainInternal.class, getToolChain().get());
PlatformToolProvider toolProvider = toolChain.select(targetPlatform);
return toolProvider.newCompiler(SwiftCompileSpec.class);
}
@TaskAction
void compile(IncrementalTaskInputs inputs) {
final List removedFiles = Lists.newArrayList();
final Set changedFiles = Sets.newHashSet();
boolean isIncremental = inputs.isIncremental();
// TODO: This should become smarter and move into the compiler infrastructure instead
// of the task, similar to how the other native languages are done.
// For now, this does a rudimentary incremental build analysis by looking at
// which files changed and marking the compilation incremental or not.
if (isIncremental) {
inputs.outOfDate(new Action() {
@Override
public void execute(InputFileDetails inputFileDetails) {
if (inputFileDetails.isModified()) {
changedFiles.add(inputFileDetails.getFile());
}
}
});
inputs.removed(new Action() {
@Override
public void execute(InputFileDetails removed) {
removedFiles.add(removed.getFile());
}
});
Set allSourceFiles = getSource().getFiles();
if (!allSourceFiles.containsAll(changedFiles)) {
// If a non-source file changed, the compilation cannot be incremental
// due to the way the Swift compiler detects changes from other modules
isIncremental = false;
}
}
BuildOperationLogger operationLogger = getServices().get(BuildOperationLoggerFactory.class).newOperationLogger(getName(), getTemporaryDir());
NativePlatformInternal targetPlatform = Cast.cast(NativePlatformInternal.class, this.targetPlatform.get());
SwiftCompileSpec spec = createSpec(operationLogger, isIncremental, changedFiles, removedFiles, targetPlatform);
Compiler baseCompiler = new IncrementalSwiftCompiler(createCompiler(), getOutputs(), compilerOutputFileNamingSchemeFactory);
Compiler loggingCompiler = BuildOperationLoggingCompilerDecorator.wrap(baseCompiler);
WorkResult result = loggingCompiler.execute(spec);
setDidWork(result.getDidWork());
}
private SwiftCompileSpec createSpec(BuildOperationLogger operationLogger, boolean isIncremental, Collection changedFiles, Collection removedFiles, NativePlatformInternal targetPlatform) {
SwiftCompileSpec spec = new DefaultSwiftCompileSpec();
spec.setModuleName(moduleName.getOrNull());
spec.setModuleFile(moduleFile.get().getAsFile());
for (File file : modules.getFiles()) {
if (file.isFile()) {
spec.include(file.getParentFile());
} else {
spec.include(file);
}
}
spec.setTargetPlatform(targetPlatform);
spec.setTempDir(getTemporaryDir());
spec.setObjectFileDir(objectFileDir.get().getAsFile());
spec.source(getSource());
spec.setRemovedSourceFiles(removedFiles);
spec.setChangedFiles(changedFiles);
// Convert Swift-like macros to a Map like NativeCompileSpec expects
Map macros = new LinkedHashMap();
for (String macro : getMacros().get()) {
macros.put(macro, null);
}
spec.setMacros(macros);
spec.args(getCompilerArgs().get());
spec.setDebuggable(getDebuggable().get());
spec.setOptimized(getOptimized().get());
spec.setIncrementalCompile(isIncremental);
spec.setOperationLogger(operationLogger);
spec.setSourceCompatibility(sourceCompatibility.get());
return spec;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy