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

Cpp: Link to threads library #3794

Merged
merged 1 commit into from
Aug 28, 2022
Merged

Cpp: Link to threads library #3794

merged 1 commit into from
Aug 28, 2022

Conversation

Krzmbrzl
Copy link
Contributor

As detailed in #3708, it is necessary to link against the (p)threads
library in order to be able to use std::call_once without producing
linker errors.

Since this function is frequently used in ANTLR's cpp version, this
commit ensures that the respective library is always linked against in
order to avoid this error, even if downstream users are not explicitly
linking against an appropriate threads library.

Fixes #3708

Copy link
Contributor

@Technius Technius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there also needs to be a find_dependency(Threads) call added to runtime/Cpp/cmake/antlr4-runtime.cmake.in

@Krzmbrzl
Copy link
Contributor Author

@Technius like this?

@parrt
Copy link
Member

parrt commented Aug 26, 2022

I'm nervous about changing the C++ target since I know so little about C++ these days. What will this break in existing code if we link it this way?

@parrt
Copy link
Member

parrt commented Aug 26, 2022

Looks like we are getting C++ errors:

[INFO] Running org.antlr.v4.test.runtime.cpp.CppRuntimeTests
java.lang.Exception: can't run cmake on antlr c++ runtime
	at org.antlr.v4.test.runtime.RuntimeRunner.runCommand(RuntimeRunner.java:315)
	at org.antlr.v4.test.runtime.cpp.CppRunner.initRuntime(CppRunner.java:92)
	at org.antlr.v4.test.runtime.RuntimeRunner.initAntlrRuntimeIfRequired(RuntimeRunner.java:263)
	at org.antlr.v4.test.runtime.RuntimeRunner.run(RuntimeRunner.java:173)
	at org.antlr.v4.test.runtime.RuntimeTests.test(RuntimeTests.java:172)
	at org.antlr.v4.test.runtime.RuntimeTests.lambda$runtimeTests$1(RuntimeTests.java:101)
	at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.lambda$execute$0(DynamicTestTestDescriptor.java:53)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.api.extension.InvocationInterceptor.interceptDynamicTest(InvocationInterceptor.java:167)
	at org.junit.jupiter.api.extension.InvocationInterceptor.interceptDynamicTest(InvocationInterceptor.java:184)
	at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.lambda$execute$1(DynamicTestTestDescriptor.java:61)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptorCall.lambda$ofVoid$0(InvocationInterceptorChain.java:78)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.execute(DynamicTestTestDescriptor.java:60)
	at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.execute(DynamicTestTestDescriptor.java:32)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
Ignore ExtraTokensAndAltLabels
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.submit(ForkJoinPoolHierarchicalTestExecutorService.java:118)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(NodeTestTask.java:226)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(NodeTestTask.java:204)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEachOrdered(ReferencePipeline.java:502)
	at org.junit.jupiter.engine.descriptor.DynamicContainerTestDescriptor.execute(DynamicContainerTestDescriptor.java:67)
	at org.junit.jupiter.engine.descriptor.DynamicContainerTestDescriptor.execute(DynamicContainerTestDescriptor.java:33)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
	at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.InterruptedException: -- Building without demo. To enable demo build use: -DWITH_DEMO=True
-- The C compiler identification is AppleClang 13.0.0.13000029
-- The CXX compiler identification is AppleClang 13.0.0.13000029
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode_13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode_13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Found Python: /usr/local/Frameworks/Python.framework/Versions/3.9/bin/python3.9 (found version "3.9.13") found components: Interpreter 
-- Configuring incomplete, errors occurred!
See also "/Users/runner/work/antlr4/antlr4/runtime/Cpp/CMakeFiles/CMakeOutput.log".
See also "/Users/runner/work/antlr4/antlr4/runtime/Cpp/CMakeFiles/CMakeError.log".
CMake Deprecation Warning at CMakeLists.txt:42 (CMAKE_POLICY):
  The OLD behavior for policy CMP0054 will be removed from a future version
  of CMake.

  The cmake-policies(7) manual explains that the OLD behaviors of all
  policies are deprecated and that a policy should be set to OLD only under
  specific short-term circumstances.  Projects should be ported to the NEW
  behavior and not rely on setting a policy to OLD.

@Krzmbrzl
Copy link
Contributor Author

I'm nervous about changing the C++ target since I know so little about C++ these days

Well without this, it just doesn't work at all. See #3708

@Krzmbrzl
Copy link
Contributor Author

can't run cmake on antlr c++ runtime

Does it provide some more detailed info on that matter somewhere?

@parrt parrt mentioned this pull request Aug 27, 2022
10 tasks
@parrt
Copy link
Member

parrt commented Aug 27, 2022

Indeed i see std::call_once invoked. How does that link w/o pthreads ever? it's called in lexer init so must execute.

This is created during testing antlr. Does it look like pthreads or abseil?

$ symbols libantlr4-runtime.dylib | grep call_once
                0x00000000000714d0 (    0x10) void std::__1::__call_once_proxy<std::__1::tuple<void (&)()> >(void*) [FUNC, NameNList, MangledNameNList, Merged, NList, FunctionStarts] 
                0x0000000000074a46 (     0x6) DYLD-STUB$$std::__1::__call_once(unsigned long volatile&, void*, void (*)(void*)) [DYLD-STUB, LENGTH, NameNList, MangledNameNList, NList] 

Ah. looks like -pthread is used to build during testing rig.

@parrt
Copy link
Member

parrt commented Aug 28, 2022

Wow. That CMakeLists.txt file is insane. Ugh. Anyway, having trouble getting cmake to build arm64 on mac silicon. This works but defaults to x86 otherwise (latest cmake):

$ cmake . -D CMAKE_OSX_ARCHITECTURES="arm64; x86_64"

Then linking against, this works:

$ clang++ -g -std=c++17 -I /Users/parrt/antlr/code/antlr4/runtime/Cpp/runtime/src -L. -lantlr4-runtime *.cpp

@Krzmbrzl
Copy link
Contributor Author

How does that link w/o pthreads ever?

I'm not sure - maybe the symbol lookup is deferred until the lib is actually loaded and if no suitable candidate is found, the function just throws the encountered exception 🤷

@Krzmbrzl
Copy link
Contributor Author

Ah, I figured out why the CI is failing:

CMake Error at runtime/CMakeLists.txt:73 (target_link_libraries):
The keyword signature for target_link_libraries has already been used with
the target "antlr4_shared". All uses of target_link_libraries with a
target must be either all-keyword or all-plain

As detailed in antlr#3708, it is necessary to link against the (p)threads
library in order to be able to use std::call_once without producing
linker errors.

Since this function is frequently used in ANTLR's cpp version, this
commit ensures that the respective library is always linked against in
order to avoid this error, even if downstream users are not explicitly
linking against an appropriate threads library.

Fixes antlr#3708

Signed-off-by: Robert Adam <dev@robert-adam.de>

Co-authored-by: Bryan Tan <Technius@users.noreply.github.com>
@parrt
Copy link
Member

parrt commented Aug 28, 2022

hooray! ok, so from your perspective this is now ready for merging? It looks a lot safer now (and I also learned something about C++ again!).

@parrt parrt added this to the 4.11 milestone Aug 28, 2022
@Krzmbrzl
Copy link
Contributor Author

Yep, from my POV this is ready :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants