firstfloorsoftware / flutter_sodium

Flutter bindings for libsodium
BSD 3-Clause "New" or "Revised" License
102 stars 46 forks source link

iOS Build Errors: no rule to process file, UnsafeMutablePointer<_>' to expected argument type 'OpaquePointer? #17

Closed 5inline closed 5 years ago

5inline commented 5 years ago

Created a new Flutter project with -i swift -a kotlin options, added flutter_sodium: ^0.0.9 to pubspec.yaml.

During debug build, I get the following errors:

Launching lib/main.dart on iPhone Xʀ in debug mode...
Xcode build done.                                            3.1s
Failed to build iOS app
Error output from Xcode build:
↳
    ** BUILD FAILED **
Xcode's output:
↳
    === BUILD TARGET flutter_sodium OF PROJECT Pods WITH CONFIGURATION Debug ===
    warning: no rule to process file '~/.pub-cache/hosted/pub.dartlang.org/flutter_sodium-0.0.9/ios/Classes/libsodium-ios/lib/libsodium.a' of type archive.ar for architecture x86_64
    === BUILD TARGET flutter_sodium OF PROJECT Pods WITH CONFIGURATION Debug ===
   ~/.pub-cache/hosted/pub.dartlang.org/flutter_sodium-0.0.9/ios/Classes/SwiftFlutterSodiumPlugin.swift:1358:50: error: cannot convert value of type 'UnsafeMutablePointer<_>' to expected argument type 'OpaquePointer?'
              flutter_sodium.crypto_generichash_init(statePtr, keyPtr, key.count, outlen)
                                                     ^~~~~~~~
   ~/.pub-cache/hosted/pub.dartlang.org/flutter_sodium-0.0.9/ios/Classes/SwiftFlutterSodiumPlugin.swift:1364:48: error: cannot convert value of type 'UnsafeMutablePointer<_>' to expected argument type 'OpaquePointer?'
            flutter_sodium.crypto_generichash_init(statePtr, nil, 0, outlen)
                                                   ^~~~~~~~
   ~/.pub-cache/hosted/pub.dartlang.org/flutter_sodium-0.0.9/ios/Classes/SwiftFlutterSodiumPlugin.swift:1378:50: error: cannot convert value of type 'UnsafeMutablePointer<_>' to expected argument type 'OpaquePointer?'
            flutter_sodium.crypto_generichash_update(statePtr, iPtr, CUnsignedLongLong(i.count))
                                                     ^~~~~~~~
   ~/.pub-cache/hosted/pub.dartlang.org/flutter_sodium-0.0.9/ios/Classes/SwiftFlutterSodiumPlugin.swift:1394:49: error: cannot convert value of type 'UnsafeMutablePointer<_>' to expected argument type 'OpaquePointer?'
            flutter_sodium.crypto_generichash_final(statePtr, outPtr, outlen)
                                                    ^~~~~~~~
Could not build the application for the simulator.

Error launching application on iPhone Xʀ.
Exited (sigterm)

$ flutter doctor

[✓] Flutter (Channel stable, v1.2.1, on Mac OS X 10.14.4 18E226, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.2)
[✓] Android Studio (version 3.3)
[✓] VS Code (version 1.33.1)
[✓] Connected device (1 available)

• No issues found!

Podfile

# Uncomment this line to define a global platform for your project
platform :ios, '9.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def parse_KV_file(file, separator='=')
  file_abs_path = File.expand_path(file)
  if !File.exists? file_abs_path
    return [];
  end
  pods_ary = []
  skip_line_start_symbols = ["#", "/"]
  File.foreach(file_abs_path) { |line|
      next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
      plugin = line.split(pattern=separator)
      if plugin.length == 2
        podname = plugin[0].strip()
        path = plugin[1].strip()
        podpath = File.expand_path("#{path}", file_abs_path)
        pods_ary.push({:name => podname, :path => podpath});
      else
        puts "Invalid plugin specification: #{line}"
      end
  }
  return pods_ary
end

target 'Runner' do
  use_frameworks!

  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
  # referring to absolute paths on developers' machines.
  system('rm -rf .symlinks')
  system('mkdir -p .symlinks/plugins')

  # Flutter Pods
  generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
  if generated_xcode_build_settings.empty?
    puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
  end
  generated_xcode_build_settings.map { |p|
    if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
      symlink = File.join('.symlinks', 'flutter')
      File.symlink(File.dirname(p[:path]), symlink)
      pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
    end
  }

  # Plugin Pods
  plugin_pods = parse_KV_file('../.flutter-plugins')
  plugin_pods.map { |p|
    symlink = File.join('.symlinks', 'plugins', p[:name])
    File.symlink(p[:path], symlink)
    pod p[:name], :path => File.join(symlink, 'ios')
  }
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
      config.build_settings['SWIFT_VERSION'] = '4.2'
    end
  end
end
5inline commented 5 years ago

Downgrading to XCode 9.x, and using SWIFT_VERSION = '3.2' seems to build successfully.

kozw commented 5 years ago

Thanks for the follow-up. Swift (and Java) interop is a bit of a mess. I'm currently working on a FFI rewrite of flutter_sodium, where both Swift and Java are no longer needed. Dart FFI is currently in preview, and will hopefully be available soon.

drriguz commented 5 years ago

yeah, hope to use FFI version of flutter_sodium~

5inline commented 5 years ago

Thanks for the follow-up. Swift (and Java) interop is a bit of a mess. I'm currently working on a FFI rewrite of flutter_sodium, where both Swift and Java are no longer needed. Dart FFI is currently in preview, and will hopefully be available soon.

Thanks for the hard work already. Do you know if there is a way to get it to build in Xcode 10? Seems like app store submissions won't be accepted unless built in Xcode 10...

s-j-a commented 5 years ago

I have this compiling on Xcode 10 Swift 5.0, made the following changes to the SwiftFlutterSodiumPlugin.swift file, tested cryptoBoxSeal and Open seems to work. The changes to the three functions that were were giving errors are as below

private func crypto_generichash_init(call: FlutterMethodCall) -> Any { let args = call.arguments as! NSDictionary let key: Data? = (args["key"] as? FlutterStandardTypedData)?.data let outlen = args["outlen"] as! Int var ret: Int32 = -1
var state = Data(count: crypto_generichash_statebytes()) // Added these two lines let umBytes = UnsafeMutablePointer.allocate(capacity: crypto_generichash_statebytes()) let oP = OpaquePointer(umBytes)

if let key = key {
  **// Removed this line: ret = state.withUnsafeMutableBytes { statePtr in** 
        key.withUnsafeBytes { keyPtr in 
          **flutter_sodium.crypto_generichash_init(oP, keyPtr, key.count, outlen)
          // Old function call: flutter_sodium.crypto_generichash_init(statePtr, keyPtr, key.count, outlen)**
        }
  **// Removed this bracket: }** 
}
else {
  ret = state.withUnsafeMutableBytes { statePtr in 
    **// Old function call: flutter_sodium.crypto_generichash_init(statePtr, nil, 0, outlen)
    flutter_sodium.crypto_generichash_init(oP, nil, 0, outlen)**

  }
}
return error(ret: ret) ?? FlutterStandardTypedData.init(bytes: state)

}

private func crypto_generichash_update(call: FlutterMethodCall) -> Any { let args = call.arguments as! NSDictionary var state = (args["state"] as! FlutterStandardTypedData).data // Added this line let state2 = args["state"] as! OpaquePointer let i = (args["in"] as! FlutterStandardTypedData).data

let ret = state.withUnsafeMutableBytes { statePtr in 
  i.withUnsafeBytes { iPtr in 
    **// Old function call: flutter_sodium.crypto_generichash_update(statePtr, iPtr, CUnsignedLongLong(i.count))
    flutter_sodium.crypto_generichash_update(state2, iPtr, CUnsignedLongLong(i.count))**
  }
}
return error(ret: ret) ?? FlutterStandardTypedData.init(bytes: state)

}

private func crypto_generichash_final(call: FlutterMethodCall) -> Any { let args = call.arguments as! NSDictionary var state = (args["state"] as! FlutterStandardTypedData).data // Added this line let state2 = args["state"] as! OpaquePointer let outlen = args["outlen"] as! Int

var out = Data(count: outlen)

let ret = state.withUnsafeMutableBytes { statePtr in 
  out.withUnsafeMutableBytes { outPtr in 
    **// Old function call: flutter_sodium.crypto_generichash_final(statePtr, outPtr, outlen)
    flutter_sodium.crypto_generichash_final(state2, outPtr, outlen)**
  }
}
return error(ret: ret) ?? FlutterStandardTypedData.init(bytes: out)

}

Aithoagon commented 5 years ago

I have this compiling on Xcode 10 Swift 5.0, made the following changes to the SwiftFlutterSodiumPlugin.swift file, tested cryptoBoxSeal and Open seems to work. The changes to the three functions that were were giving errors are as below

private func crypto_generichash_init(call: FlutterMethodCall) -> Any { let args = call.arguments as! NSDictionary let key: Data? = (args["key"] as? FlutterStandardTypedData)?.data let outlen = args["outlen"] as! Int var ret: Int32 = -1 var state = Data(count: crypto_generichash_statebytes()) // Added these two lines let umBytes = UnsafeMutablePointer.allocate(capacity: crypto_generichash_statebytes()) let oP = OpaquePointer(umBytes)

if let key = key {
  **// Removed this line: ret = state.withUnsafeMutableBytes { statePtr in** 
        key.withUnsafeBytes { keyPtr in 
          **flutter_sodium.crypto_generichash_init(oP, keyPtr, key.count, outlen)
          // Old function call: flutter_sodium.crypto_generichash_init(statePtr, keyPtr, key.count, outlen)**
        }
  **// Removed this bracket: }** 
}
else {
  ret = state.withUnsafeMutableBytes { statePtr in 
    **// Old function call: flutter_sodium.crypto_generichash_init(statePtr, nil, 0, outlen)
    flutter_sodium.crypto_generichash_init(oP, nil, 0, outlen)**

  }
}
return error(ret: ret) ?? FlutterStandardTypedData.init(bytes: state)

}

private func crypto_generichash_update(call: FlutterMethodCall) -> Any { let args = call.arguments as! NSDictionary var state = (args["state"] as! FlutterStandardTypedData).data // Added this line let state2 = args["state"] as! OpaquePointer let i = (args["in"] as! FlutterStandardTypedData).data

let ret = state.withUnsafeMutableBytes { statePtr in 
  i.withUnsafeBytes { iPtr in 
    **// Old function call: flutter_sodium.crypto_generichash_update(statePtr, iPtr, CUnsignedLongLong(i.count))
    flutter_sodium.crypto_generichash_update(state2, iPtr, CUnsignedLongLong(i.count))**
  }
}
return error(ret: ret) ?? FlutterStandardTypedData.init(bytes: state)

}

private func crypto_generichash_final(call: FlutterMethodCall) -> Any { let args = call.arguments as! NSDictionary var state = (args["state"] as! FlutterStandardTypedData).data // Added this line let state2 = args["state"] as! OpaquePointer let outlen = args["outlen"] as! Int

var out = Data(count: outlen)

let ret = state.withUnsafeMutableBytes { statePtr in 
  out.withUnsafeMutableBytes { outPtr in 
    **// Old function call: flutter_sodium.crypto_generichash_final(statePtr, outPtr, outlen)
    flutter_sodium.crypto_generichash_final(state2, outPtr, outlen)**
  }
}
return error(ret: ret) ?? FlutterStandardTypedData.init(bytes: out)

}

same for me. tried this but got "error: generic parameter 'Pointee' could not be inferred let umBytes = UnsafeMutablePointer.allocate(capacity: crypto_generichash_statebytes()) ^ Swift.UnsafeMutablePointer:1:15: note: 'Pointee' declared as parameter to type 'UnsafeMutablePointer' public struct UnsafeMutablePointer : _Pointer {"

any update on this issue?

s-j-a commented 5 years ago

Hi Claudio, looks like you have missed the in the let statement, should read as follows let umBytes = UnsafeMutablePointer.allocate(capacity: crypto_generichash_statebytes())

I have also now added the following two lines before the return in an attempt to ensure that the state ptr is also returned

let bufferPointer = UnsafeRawPointer(umBytes)
state = Data(bytes: bufferPointer, count: crypto_generichash_statebytes())

Ensure that SWIFT_VERSION in your podfile is 5.0, otherwise the compile will throw even more errors !

note of caution: although these changes allow the code to compile I have not thoroughly tested these changes to ensure that these functions continue to work as intended, please test for your use case and use carefully.

the best solution would be an updated solution from the author.

s-j-a commented 5 years ago

for some reason the submission removes the UInt8 type in angled brackets from the text !

I'll try again, the let should look like this let umBytes = UnsafeMutablePointer<UInt8>.allocate(capacity: crypto_generichash_statebytes())

kozw commented 5 years ago

This is good feedback. I'll try to update the source asap.

Keep in mind that the current flutter_sodium source will be replaced eventually by an FFI implementation

kozw commented 5 years ago

Version 0.0.10 has just been made available addressing the problems mentioned here.