- // update which form of ObjC dylibs are being linked
- switch ( dylibFile->objCConstraint() ) {
- case ld::File::objcConstraintNone:
- break;
- case ld::File::objcConstraintRetainRelease:
- if ( _internal.objcDylibConstraint == ld::File::objcConstraintGC )
- throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path());
- if ( _options.objcGcOnly() )
- throwf("command line specified -objc_gc_only, but dylib is retain/release based: %s", file.path());
- if ( _options.objcGc() )
- throwf("command line specified -objc_gc, but dylib is retain/release based: %s", file.path());
- _internal.objcDylibConstraint = ld::File::objcConstraintRetainRelease;
- break;
- case ld::File::objcConstraintRetainReleaseOrGC:
- if ( _internal.objcDylibConstraint == ld::File::objcConstraintNone )
- _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseOrGC;
- break;
- case ld::File::objcConstraintGC:
- if ( _internal.objcDylibConstraint == ld::File::objcConstraintRetainRelease )
- throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path());
- _internal.objcDylibConstraint = ld::File::objcConstraintGC;
- break;
+ // Check dylib for bitcode, if the library install path is relative path or @rpath, it has to contain bitcode
+ if ( _options.bundleBitcode() ) {
+ bool isSystemFramework = ( dylibFile->installPath() != NULL ) && ( dylibFile->installPath()[0] == '/' );
+ if ( dylibFile->getBitcode() == NULL && !isSystemFramework ) {
+ // Check if the dylib is from toolchain by checking the path
+ char tcLibPath[PATH_MAX];
+ char ldPath[PATH_MAX];
+ char tempPath[PATH_MAX];
+ uint32_t bufSize = PATH_MAX;
+ // toolchain library path should pointed to *.xctoolchain/usr/lib
+ if ( _NSGetExecutablePath(ldPath, &bufSize) != -1 ) {
+ if ( realpath(ldPath, tempPath) != NULL ) {
+ char* lastSlash = strrchr(tempPath, '/');
+ if ( lastSlash != NULL )
+ strcpy(lastSlash, "/../lib");
+ }
+ }
+ // Compare toolchain library path to the dylib path
+ if ( realpath(tempPath, tcLibPath) == NULL ||
+ realpath(dylibFile->path(), tempPath) == NULL ||
+ strncmp(tcLibPath, tempPath, strlen(tcLibPath)) != 0 ) {
+ _options.platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ switch ( platform ) {
+ case ld::kPlatform_macOS:
+ case ld::kPlatform_bridgeOS:
+ case ld::kPlatform_iOSMac:
+ case ld::kPlatform_unknown:
+ warning("all bitcode will be dropped because '%s' was built without bitcode. "
+ "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+ _internal.filesWithBitcode.clear();
+ _internal.dropAllBitcode = true;
+ break;
+ case ld::kPlatform_iOS:
+ case ld::kPlatform_iOSSimulator:
+ throwf("'%s' does not contain bitcode. "
+ "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+ break;
+ case ld::kPlatform_watchOS:
+ case ld::kPlatform_watchOSSimulator:
+ case ld::kPlatform_tvOS:
+ case ld::kPlatform_tvOSSimulator:
+ throwf("'%s' does not contain bitcode. "
+ "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor", file.path());
+ break;
+ }
+ });
+ }
+ }
+ // Error on bitcode marker in non-system frameworks if -bitcode_verify is used
+ if ( _options.verifyBitcode() && !isSystemFramework &&
+ dylibFile->getBitcode() != NULL && dylibFile->getBitcode()->isMarker() )
+ throwf("bitcode bundle could not be generated because '%s' was built without full bitcode. "
+ "All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install build",
+ dylibFile->path());
+ }
+
+ // Don't allow swift frameworks to link other swift frameworks.
+ if ( !_internal.firstSwiftDylibFile && _options.outputKind() == Options::kDynamicLibrary
+ && file.swiftVersion() != 0 && getenv("LD_DISALLOW_SWIFT_LINKING_SWIFT")) {
+ // Check that we aren't a whitelisted path.
+ bool inWhiteList = false;
+ const char *whitelistedPaths[] = { "/System/Library/PrivateFrameworks/Swift" };
+ for (auto whitelistedPath : whitelistedPaths) {
+ if (!strncmp(whitelistedPath, dylibFile->installPath(), strlen(whitelistedPath))) {
+ inWhiteList = true;
+ break;
+ }
+ }
+ if (!inWhiteList) {
+ _internal.firstSwiftDylibFile = dylibFile;
+ }
+ }
+
+ // <rdar://problem/25680358> verify dylibs use same version of Swift language
+ if ( file.swiftVersion() != 0 ) {
+ if ( _internal.swiftVersion == 0 ) {
+ _internal.swiftVersion = file.swiftVersion();
+ }
+ else if ( file.swiftVersion() != _internal.swiftVersion ) {
+ char fileVersion[64];
+ char otherVersion[64];
+ Options::userReadableSwiftVersion(file.swiftVersion(), fileVersion);
+ Options::userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
+ if ( file.swiftVersion() > _internal.swiftVersion ) {
+ if ( _options.warnOnSwiftABIVersionMismatches() ) {
+ warning("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ } else {
+ throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ }
+ }
+ else {
+ if ( _options.warnOnSwiftABIVersionMismatches() ) {
+ warning("%s compiled with older version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ } else {
+ throwf("%s compiled with older version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ }
+ }
+ }