Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linking globals named 'OBJC_CLASS_$_GatewayApiLong': symbol multiply defined! #4238

Closed
sentinelweb opened this issue Jun 30, 2022 · 26 comments
Closed
Labels
⌛ Waiting for info More information is required

Comments

@sentinelweb
Copy link

sentinelweb commented Jun 30, 2022

Summary
I am testing using the Kotlin Multiplatform version of Apollo. Our schema works fine when compiling for android but we are getting the above error when building iOS library : ./gradlew clean gateway_api:iosX64MainBinaries

Version
3.3.2

Description
Add context about the problem here. How it happened and how to reproduce it:

Our schema has no scalar Long declaration but there are quite a few places that use an adhoc scalar Long definition in fields (e.g. below)

I am guessing this is the cause of the above error so I wanted to check if simply declaring a scalar Long in the schema and using it for fields would be the correct solution? As it might quite a big change for our organization.

Or is there some compilation flag i could add that would ignore this error?

i have also tried adding codegenModels.set("responseBased") and modifying our code to use this codegen structure - but i ended up getting the same error after the change.

{
  "name": "netUnitsSold",
  "description": "Net unit sold across aggregation",
  "args": [],
  "type": {
    "kind": "SCALAR",
    "name": "Long",
    "ofType": null
  },
  "isDeprecated": false,
  "deprecationReason": null
},

This is the error stacktrace when executing ./gradlew clean gateway_api:iosX64MainBinaries - same for pod install in XCode.

> Task :gateway_api:linkPodDebugFrameworkIosX64 FAILED
e: Compilation failed: Linking globals named 'OBJC_CLASS_$_GatewayApiLong': symbol multiply defined!

 * Source files: 
 * Compiler version info: Konan: 1.6.21 / Kotlin: 1.6.21
 * Output kind: FRAMEWORK

e: java.lang.Error: Linking globals named 'OBJC_CLASS_$_GatewayApiLong': symbol multiply defined!
        at org.jetbrains.kotlin.backend.konan.llvm.DefaultLlvmDiagnosticHandler.handle(diagnosticReport.kt:24)
        at org.jetbrains.kotlin.backend.konan.llvm.LlvmDiagnosticCollector.flush(diagnostics.kt:36)
        at org.jetbrains.kotlin.backend.konan.llvm.LinkModulesKt.llvmLinkModules2(linkModules.kt:36)
        at org.jetbrains.kotlin.backend.konan.llvm.objc.LinkObjCKt.linkObjC(linkObjC.kt:32)
        at org.jetbrains.kotlin.backend.konan.CompilerOutputKt.linkAllDependencies(CompilerOutput.kt:81)
        at org.jetbrains.kotlin.backend.konan.CompilerOutputKt.linkBitcodeDependencies(CompilerOutput.kt:125)
        at org.jetbrains.kotlin.backend.konan.llvm.BitcodePhasesKt$linkBitcodeDependenciesPhase$1.invoke(BitcodePhases.kt:349)
        at org.jetbrains.kotlin.backend.konan.llvm.BitcodePhasesKt$linkBitcodeDependenciesPhase$1.invoke(BitcodePhases.kt:346)
        at org.jetbrains.kotlin.backend.konan.KonanLoweringPhasesKt$makeKonanModuleOpPhase$1.invoke(KonanLoweringPhases.kt:65)
        at org.jetbrains.kotlin.backend.konan.KonanLoweringPhasesKt$makeKonanModuleOpPhase$1.invoke(KonanLoweringPhases.kt:63)
        at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
        at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29)
        at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
        at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:22)
        at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
        at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29)
        at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
        at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:43)
        at org.jetbrains.kotlin.backend.konan.KonanDriverKt.runTopLevelPhases(KonanDriver.kt:34)
        at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:88)
        at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:37)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:91)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:43)
        at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:93)
        at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:71)
        at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:40)
        at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:168)
        at org.jetbrains.kotlin.cli.bc.K2Native$Companion$mainNoExitWithGradleRenderer$1.invoke(K2Native.kt:412)
        at org.jetbrains.kotlin.cli.bc.K2Native$Companion$mainNoExitWithGradleRenderer$1.invoke(K2Native.kt:411)
        at org.jetbrains.kotlin.util.UtilKt.profileIf(Util.kt:22)
        at org.jetbrains.kotlin.util.UtilKt.profile(Util.kt:16)
        at org.jetbrains.kotlin.cli.bc.K2Native$Companion.mainNoExitWithGradleRenderer(K2Native.kt:411)
        at org.jetbrains.kotlin.cli.bc.K2NativeKt.mainNoExitWithGradleRenderer(K2Native.kt:666)
        at org.jetbrains.kotlin.cli.utilities.MainKt$daemonMain$1.invoke(main.kt:62)
        at org.jetbrains.kotlin.cli.utilities.MainKt$daemonMain$1.invoke(main.kt:62)
        at org.jetbrains.kotlin.cli.utilities.MainKt.mainImpl(main.kt:17)
        at org.jetbrains.kotlin.cli.utilities.MainKt.daemonMain(main.kt:62)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.runInProcess(KotlinToolRunner.kt:136)
        at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.run(KotlinToolRunner.kt:81)
        at org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink.compile(KotlinNativeTasks.kt:657)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
        at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:242)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
        at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:227)
        at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:210)
        at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:193)
        at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:171)
        at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:89)
        at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:40)
        at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:53)
        at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:50)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:50)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:40)
        at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:68)
        at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:38)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:48)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:36)
        at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:41)
        at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:74)
        at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:51)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:29)
        at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:61)
        at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:42)
        at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:60)
        at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:27)
        at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:180)
        at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$1(BuildCacheStep.java:75)
        at org.gradle.internal.Either$Right.fold(Either.java:175)
        at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:59)
        at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:73)
        at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:48)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:36)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:25)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:36)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:22)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:110)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:56)
        at java.base/java.util.Optional.orElseGet(Optional.java:362)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:56)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:38)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:73)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:44)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:89)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:50)
        at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:114)
        at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:57)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:76)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:50)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNoEmptySources(SkipEmptyWorkStep.java:249)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNoEmptySources(SkipEmptyWorkStep.java:204)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:83)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:54)
        at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:32)
        at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:21)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
        at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:43)
        at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:31)
        at org.gradle.internal.execution.steps.AssignWorkspaceStep.lambda$execute$0(AssignWorkspaceStep.java:40)
        at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:287)
        at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:40)
        at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:30)
        at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:37)
        at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:27)
        at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:44)
        at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:33)
        at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:76)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:144)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:133)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:74)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:333)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:320)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:313)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:299)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:143)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:227)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:218)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:140)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:830)


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':gateway_api:linkPodDebugFrameworkIosX64'.
> Compilation finished with errors
@BoD
Copy link
Contributor

BoD commented Jun 30, 2022

Hi! Thanks for reporting this!

This doesn't immediately ring a bell 🤔

However I'm not sure I understand what you mean by "Our schema has no scalar Long" - if the netUnitsSold field shown above is of type Long then it must be declared in the schema?
On the other hand, if that wasn't the case, Apollo Kotlin should have emitted something like "Unknown type Long".

In any case if possible, it would help a lot if you could share a project so that we can reproduce and investigate this (if this can't be shared publicly feel free to send it to benoit.lubek@apollographql.com) 🙏

@sentinelweb
Copy link
Author

hi, yes sorry it is actually declared i missed it before.

In the header file generated i can see that interface (GatewayApiLong) is actually generated twice - just have to check with the org what i can share. so i'll get back soon.

thanks for the quick response.

@BoD
Copy link
Contributor

BoD commented Jun 30, 2022

Thanks! Are you in a multi-module setup by any chance (wondering if it could be a type clash).

@sentinelweb
Copy link
Author

Each schema is in it's own kmp module. The other module is very simple - it compiles fine and I can use it in the ios app. This gateway_api module has the bulk of the operations though.

@sentinelweb
Copy link
Author

sentinelweb commented Jul 1, 2022

in the generated GatewayApi.h the conflicting interfaces are:

__attribute__((swift_name("KotlinLong")))
@interface GatewayApiLong : GatewayApiNumber
- (instancetype)initWithLongLong:(long long)value;
+ (instancetype)numberWithLongLong:(long long)value;
@end;

and

__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Long")))
@interface GatewayApiLong : GatewayApiBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property (class, readonly, getter=companion) GatewayApiLongCompanion *companion __attribute__((swift_name("companion")));
@end;

__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Long.Companion")))
@interface GatewayApiLongCompanion : GatewayApiBase
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)companion __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) GatewayApiLongCompanion *shared __attribute__((swift_name("shared")));
@property (readonly) GatewayApiApollo_apiCustomScalarType *type __attribute__((swift_name("type")));
@end;

So possibly the declared scalar Long in our schema is conflicting with the KotlinLong from the default KotlinNumber interfaces?

__attribute__((swift_name("KotlinNumber")))
@interface GatewayApiNumber : NSNumber
- (instancetype)initWithChar:(char)value __attribute__((unavailable));
- (instancetype)initWithUnsignedChar:(unsigned char)value __attribute__((unavailable));
- (instancetype)initWithShort:(short)value __attribute__((unavailable));
- (instancetype)initWithUnsignedShort:(unsigned short)value __attribute__((unavailable));
- (instancetype)initWithInt:(int)value __attribute__((unavailable));
- (instancetype)initWithUnsignedInt:(unsigned int)value __attribute__((unavailable));
- (instancetype)initWithLong:(long)value __attribute__((unavailable));
- (instancetype)initWithUnsignedLong:(unsigned long)value __attribute__((unavailable));
- (instancetype)initWithLongLong:(long long)value __attribute__((unavailable));
- (instancetype)initWithUnsignedLongLong:(unsigned long long)value __attribute__((unavailable));
- (instancetype)initWithFloat:(float)value __attribute__((unavailable));
- (instancetype)initWithDouble:(double)value __attribute__((unavailable));
- (instancetype)initWithBool:(BOOL)value __attribute__((unavailable));
- (instancetype)initWithInteger:(NSInteger)value __attribute__((unavailable));
- (instancetype)initWithUnsignedInteger:(NSUInteger)value __attribute__((unavailable));
+ (instancetype)numberWithChar:(char)value __attribute__((unavailable));
+ (instancetype)numberWithUnsignedChar:(unsigned char)value __attribute__((unavailable));
+ (instancetype)numberWithShort:(short)value __attribute__((unavailable));
+ (instancetype)numberWithUnsignedShort:(unsigned short)value __attribute__((unavailable));
+ (instancetype)numberWithInt:(int)value __attribute__((unavailable));
+ (instancetype)numberWithUnsignedInt:(unsigned int)value __attribute__((unavailable));
+ (instancetype)numberWithLong:(long)value __attribute__((unavailable));
+ (instancetype)numberWithUnsignedLong:(unsigned long)value __attribute__((unavailable));
+ (instancetype)numberWithLongLong:(long long)value __attribute__((unavailable));
+ (instancetype)numberWithUnsignedLongLong:(unsigned long long)value __attribute__((unavailable));
+ (instancetype)numberWithFloat:(float)value __attribute__((unavailable));
+ (instancetype)numberWithDouble:(double)value __attribute__((unavailable));
+ (instancetype)numberWithBool:(BOOL)value __attribute__((unavailable));
+ (instancetype)numberWithInteger:(NSInteger)value __attribute__((unavailable));
+ (instancetype)numberWithUnsignedInteger:(NSUInteger)value __attribute__((unavailable));
@end;

i don't know if that helps - still checking about the schema but it might take a few days .. sorry

@BoD
Copy link
Contributor

BoD commented Jul 1, 2022

Ooh good catch, yes this is probably the culprit. Can you try to rename the Long scalar definition and usage to, for instance, MyLong in your schema, to see if that resolves the issue?

By the way, I noticed above you showed part of your schema in json, but you can convert it to SDL instead, which is more user-friendly:

./gradlew convertApolloSchema --from=src/main/graphql/schema.json --to=src/main/graphql/schema.graphqls

@sentinelweb
Copy link
Author

It a corporate schema. So company wide. Probably you might need to change the namespaciing a bit? It's not urgent tho.

Possibly the numerical interfaces could be Klong etc? Just an idea..

@sentinelweb
Copy link
Author

sentinelweb commented Jul 1, 2022

Eg

__attribute__((swift_name("KotlinLong")))
@interface GatewayApiKotlinLong : GatewayApiNumber 

@BoD
Copy link
Contributor

BoD commented Jul 5, 2022

In this PR, we're adding an (experimental) @targetName directive that you can set on your scalar declaration (by extending it), which will be used to chose the corresponding generated Kotlin type name. You will be able to use it like this:

# In a new file named extra.graphqls, next to your schema.graphqls

extend scalar Long @targetName(name: "GatewayApiLong")

In the meantime, you can still rename the Long scalar in your schema, locally on your project, and that should probably work.

@sentinelweb
Copy link
Author

sentinelweb commented Jul 5, 2022

yes looks like that should work. I'm not sure how common it is for users to declare a scalar type with a name the same as a kotlin type (Integer, Long, Char, etc). I guess this would work for all those cases though.

when do you think it would be released? it not really urgent atm though. as we are just testing things out.

@BoD BoD added the ✔️ Fixed in SNAPSHOTs The fix has been merged and is available in SNAPSHOTs, and will be available in the next release label Jul 13, 2022
@BoD
Copy link
Contributor

BoD commented Jul 13, 2022

The @targetName directive has just been merged, so this will be in the next release, in the meantime it can be tried out with the snapshots.

@sentinelweb
Copy link
Author

on nice ... i'll give it a whirl

@sentinelweb
Copy link
Author

So i am trying this out. I have got the 3.4.1-SNAPSHOT in the project - i can see it loaded

I have extra.graphqls:

# In a new file named extra.graphqls, next to your schema.graphqls

extend scalar Long @targetName(name: "GatewayApiMyLong")

but it shows errors:

The extension 'Long' type is missing its base underlying type
'Long' tried to use an undeclared directive 'targetName'

Wondering if you have any suggestions for checking it?

@BoD
Copy link
Contributor

BoD commented Jul 15, 2022

Thanks for trying it out! Just making sure, are these messages you're seeing in the IDE? It's possible the directive is not known to the GraphQL plugin, so it highlights it as an error, but it will still compile OK. You can have a look at the generated code which should be in the build/generated/source/apollo/ folder of your module.

@sentinelweb
Copy link
Author

it still the same error - so looks like it not getting picked up for some reason

./gradlew clean gateway_api:iosX64MainBinaries

e: Compilation failed: Linking globals named 'OBJC_CLASS_$_GatewayApiLong': symbol multiply defined!

 * Source files: 
 * Compiler version info: Konan: 1.6.21 / Kotlin: 1.6.21
 * Output kind: FRAMEWORK

e: java.lang.Error: Linking globals named 'OBJC_CLASS_$_GatewayApiLong': symbol multiply defined!

the generated Long class is

package com.wayfair.partners.gateway.api.type

import com.apollographql.apollo3.api.CustomScalarType

public class Long {
  public companion object {
    public val type: CustomScalarType = CustomScalarType("Long", "kotlin.Any")
  }
}

@BoD
Copy link
Contributor

BoD commented Jul 15, 2022

Hmm this is odd indeed. The class should be named GatewayApiMyLong. Could this be a cache issue (have you tried to clean/rebuild?). I also pushed a mini project here that generates the correct class name, maybe you can catch any difference with your setup?

@martinbonnin martinbonnin removed the ✔️ Fixed in SNAPSHOTs The fix has been merged and is available in SNAPSHOTs, and will be available in the next release label Sep 9, 2022
@martinbonnin
Copy link
Contributor

@sentinelweb anything else we can help with here?

@martinbonnin martinbonnin added the ⌛ Waiting for info More information is required label Sep 9, 2022
@sentinelweb
Copy link
Author

sorry i missed you message - i couldn't get this to work for our use case, i cleaned and rebuilt, etc - but luckily for us the offending Long scalar declaration was move to another module so the conflict disappeared.

@allenwhite
Copy link

@BoD @martinbonnin I am seeing this issue in my Multiplatform project on the latest version of Apollo, even with the extra.graphqls solution above. Any suggestions on a way to handle this without forcing the upstream API to make changes?

@BoD
Copy link
Contributor

BoD commented Apr 6, 2023

Hi @allenwhite. If you added the @targetName directive, can you check in the generated files (<yourmodule>/build/generated/source/apollo/service/com/example/type), if you see one named Long.kt? You should not see it but see MyLong.kt (or the name you picked).

@allenwhite
Copy link

@BoD Thanks for getting back to me. Yeah I checked, I see Long.kt and the default implementation there, despite having added the @targetName directive.

@BoD
Copy link
Contributor

BoD commented Apr 6, 2023

@allenwhite Just to be sure: which version of Apollo are you on? Is the extra.graphqls file next to the schema.graphqls one (like in this sample)?

@allenwhite
Copy link

allenwhite commented Apr 6, 2023

@BoD I initially saw on an earlier version of Apollo, and updated to the latest (3.8.0) but still saw the issue. And yupp, I have that file right next to the schema file.

@BoD
Copy link
Contributor

BoD commented Apr 6, 2023

@allenwhite Would it be possible for you to provide a minimal barebones version of your project so we can have a look? (If this can't be public, you can share it to my email: benoit.lubek@apollographql.com)

@allenwhite
Copy link

allenwhite commented Apr 6, 2023

Just shot something over to you @BoD . Thanks!

@BoD
Copy link
Contributor

BoD commented Apr 7, 2023

Thanks a lot! This helped identify the issue.

For the posterity in case other people have the same issue: Apollo was explicitly configured with schemaFile.set(...) which excludes the extra.graphqls file from being considered. Removing the option solved the issue (all schema files in src/commonMain/graphql are included by default).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⌛ Waiting for info More information is required
Projects
None yet
Development

No branches or pull requests

4 participants