antlr4
                                
                                
                                
                                    antlr4 copied to clipboard
                            
                            
                            
                        Cpp: Link to threads library
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
@Technius like this?
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?
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.
                                    
                                    
                                    
                                
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
can't run cmake on antlr c++ runtime
Does it provide some more detailed info on that matter somewhere?
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.
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
                                    
                                    
                                    
                                
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 :shrug:
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
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!).
Yep, from my POV this is ready :)