/*
* Copyright 2017-present Facebook, Inc.
*
* 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 com.facebook.buck.rust;
import com.facebook.buck.cxx.CxxDescriptionEnhancer;
import com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.model.Flavor;
/** Describe the kinds of crates rustc can generate. */
public enum CrateType {
BIN(
"bin",
RustDescriptionEnhancer.RFBIN,
(n, p) -> String.format("%s%s", n, p.getBinaryExtension().map(e -> "." + e).orElse(""))),
CHECK("lib", RustDescriptionEnhancer.RFCHECK, (n, p) -> String.format("lib%s.rmeta", n)),
CHECKBIN(
"bin",
RustDescriptionEnhancer.RFCHECK,
(n, p) -> String.format("%s%s", n, p.getBinaryExtension().map(e -> "." + e).orElse(""))),
LIB(
"lib",
RustDescriptionEnhancer.RFLIB,
(n, p) -> String.format("lib%s.rlib", n)), // XXX how to tell?
RLIB("rlib", RustDescriptionEnhancer.RFRLIB, (n, p) -> String.format("lib%s.rlib", n)),
RLIB_PIC("rlib", RustDescriptionEnhancer.RFRLIB_PIC, (n, p) -> String.format("lib%s.rlib", n)),
DYLIB(
"dylib",
RustDescriptionEnhancer.RFDYLIB,
(n, p) -> String.format("lib%s.%s", n, p.getSharedLibraryExtension())),
CDYLIB(
"cdylib",
CxxDescriptionEnhancer.SHARED_FLAVOR,
(n, p) -> String.format("lib%s.%s", n, p.getSharedLibraryExtension())),
STATIC(
"staticlib",
CxxDescriptionEnhancer.STATIC_FLAVOR,
(n, p) -> String.format("lib%s.%s", n, p.getStaticLibraryExtension())),
STATIC_PIC(
"staticlib",
CxxDescriptionEnhancer.STATIC_PIC_FLAVOR,
(n, p) -> String.format("lib%s.%s", n, p.getStaticLibraryExtension())),
;
// Crate type as passed to `rustc --crate-type=`
private final String crateType;
// Flavor corresponding to this crate type
private final Flavor crateFlavor;
// Function to consruct a suitable filename, using platform naming conventions
private final RustDescriptionEnhancer.FilenameMap filenameMap;
CrateType(String crateType, Flavor flavor, RustDescriptionEnhancer.FilenameMap filename) {
this.crateType = crateType;
this.crateFlavor = flavor;
this.filenameMap = filename;
}
@Override
public String toString() {
return this.crateType;
}
public Flavor getFlavor() {
return crateFlavor;
}
/**
* Return true if this crate type is intended to be a native output (ie, not intended for further
* processing by the Rust toolchain). In other words, a binary, or a native-linkable shared or
* static object.
*
* @return Is natively usable.
*/
public boolean isNative() {
return this == BIN || this == CDYLIB || this == STATIC || this == STATIC_PIC;
}
/**
* Linking this crate needs all the dependencies available.
*
* @return Need all deps.
*/
public boolean needAllDeps() {
return this == BIN || isDynamic() || isNative();
}
/**
* Crate dynamically links with its dependents.
*
* @return Is dynamic.
*/
public boolean isDynamic() {
return this == CDYLIB || this == DYLIB;
}
/**
* Crate needs to be compiled with relocation-model=pic. Executables are currently always compiled
* with -pie, and so are also PIC.
*
* @return Needs PIC.
*/
public boolean isPic() {
return isDynamic() || this == RLIB_PIC || this == STATIC_PIC || this == BIN;
}
/**
* We're just checking the code, and generating metadata to allow dependents to check. For
* libraries this means we emit a metadata file, and binaries produce no output (they just consume
* library metadata).
*/
public boolean isCheck() {
return this == CHECK || this == CHECKBIN;
}
/**
* Returns true if the build is expected to produce output (vs is just being run for
* error-checking side-effects). The only build which produces no output is a CHECKBIN build
*/
public boolean hasOutput() {
return this != CHECKBIN;
}
/**
* Return an appropriate filename for this crate, given its type and the platform.
*
* @param name Base filename
* @param cxxPlatform Platform we're building for
* @return Path component
*/
public String filenameFor(String name, CxxPlatform cxxPlatform) {
return filenameMap.apply(name, cxxPlatform);
}
}