[使用clang ++用SCons编译Antlr4 cpp运行时。结果库给了我未定义的符号(macos)

问题描述 投票:0回答:1

我正在尝试创建一个将要...的SConstruct ...

  • Antlr4 cpp runtime构建为静态库
  • 使用Antrl4(Java应用程序)以简单的语法以cpp格式构建Lexer,Parser,Visitor和Listener。
  • [构建一个简单的程序来解析具有该语法的文件

全部在Macos(Catalina)上使用Clang ++

现在我不得不说我不是C ++专家,所以可能我想念的东西很明显……希望。

我遇到的问题是第一步和最后一步。我可以构建Antlr4运行时,但稍后不会与最终程序链接。仅仅调用#include "antlr4-runtime.h"会导致Undefined symbols for architecture x86_64错误。

奇怪的是,如果我用cmake构建Antlr4运行时,如Antlr的存储库中所述,那么链接问题就消失了。

所以我用cmake构建了它,并使用VERBOSE模式查看make如何构建各种目标文件,并确保我在Scons中使用相同的标志

带有cmake / make的输出示例:

clang++ 
-Iantlr4-master/runtime/Cpp/runtime/src 
-Iantlr4-master/runtime/Cpp/runtime/src/atn 
-Iantlr4-master/runtime/Cpp/runtime/src/dfa 
-Iantlr4-master/runtime/Cpp/runtime/src/misc 
-Iantlr4-master/runtime/Cpp/runtime/src/support 
-Iantlr4-master/runtime/Cpp/runtime/src/tree 
-Iantlr4-master/runtime/Cpp/runtime/src/tree/pattern 
-Iantlr4-master/runtime/Cpp/runtime/src/tree/xpath  
-Wall -pedantic -W -std=c++11 -stdlib=libc++ -O3 -DNDEBUG -O3 -DNDEBUG  
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk   
-Wno-overloaded-virtual -Wno-dollar-in-identifier-extension -Wno-four-char-constants  -std=gnu++11 
-o CMakeFiles/antlr4_static.dir/src/atn/PredicateTransition.cpp.o 
-c antlr4-master/runtime/Cpp/runtime/src/atn/PredicateTransition.cpp

显然,这应该是一行,但为了便于阅读,我分成多行;]]

因此,我抓住了所有这些标志并将它们放入字符串中,然后让Scons弄清楚如何将其应用于环境:

pf = env.ParseFlags('\
    -Wall -pedantic -W -O3 -std=c++11 -stdlib=libc++ -DNDEBUG -std=gnu++11 \
    -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \
    -Wno-overloaded-virtual -Wno-dollar-in-identifier-extension -Wno-four-char-constants')
env.MergeFlags(pf)

现在,我再次使用SCons构建Antlr4,这是SCons创建的命令示例:

clang++ 
-o antlr4-master/runtime/Cpp/runtime/src/atn/PredicateTransition.o 
-c 
-std=c++11 -stdlib=libc++ -Wall -pedantic -W -O3 
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk 
-Wno-overloaded-virtual -Wno-dollar-in-identifier-extension -Wno-four-char-constants -DNDEBUG 
-Iantlr4-master/runtime/Cpp/runtime/src 
antlr4-master/runtime/Cpp/runtime/src/atn/PredicateTransition.cpp

同样,我分成多行只是为了易于阅读...

我注意到的第一件事是命令中参数的顺序在SCons中无处不在,但其余部分几乎相同。不幸的是,这给了我同样的Undefined symbols for architecture x86_64错误。可能您注意到我只包含了antlr4运行时的主目录,该目录应该可以正常工作,因为所有include都从该目录开始...无论如何,我也尝试像cmake / make一样包含所有子文件夹,结果是相同。

目前我真的很笨。希望你们中的一些人能够使我朝正确的方向前进。

这是我的SConstruct文件(路径与示例不同。但是没关系)

import os
import subprocess


env = Environment(
    CC = "clang",
    CXX = "clang++",
    CXXFLAGS = ['-std=c++11', '-stdlib=libc++'],
    LINKFLAGS = ['-stdlib=libc++'],
)

env.Append(ENV = {'CLASSPATH': './dependencies/antlr4/antlr-4.8-complete.jar'})

#
# Builder for generating grammar files with antlr4 (the java app)
#

def antlr_emitter(target, source, env):
    root = os.path.splitext(source[0].name)[0]

    target  = ['./src/Parser/{}{}.cpp'.format(root, p) for p in (
        'BaseListener',
        'BaseVisitor',
        'Lexer',
        'Listener',
        'Parser',
        'Visitor'
    )]
    return target, source


AntlrBuilder = Builder(
    action='java org.antlr.v4.Tool $SOURCE -Dlanguage=Cpp -package Coral -visitor -listener -o src/Parser',
    emitter=antlr_emitter
)

env.Append(BUILDERS={'Antlr': AntlrBuilder})


#
# Cloning the Environment for Antlr4 runtime
#

antlrEnv = env.Clone()

pf = antlrEnv.ParseFlags('\
    -Wall -pedantic -W -O3 -DNDEBUG -std=gnu++11 \
    -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \
    -Wno-overloaded-virtual -Wno-dollar-in-identifier-extension -Wno-four-char-constants')
antlrEnv.MergeFlags(pf)


#
# Building in 3 steps, first the antlr4 runtime library, then the parser files with Antlr then the final program
#

AntlrRuntime = antlrEnv.Library(
                            'antlr4-runtime',
                            source = 
                                Glob('./dependencies/antlr4Runtime/*.cpp') + \
                                Glob('./dependencies/antlr4Runtime/atn/*.cpp') + \
                                Glob('./dependencies/antlr4Runtime/dfa/*.cpp') + \
                                Glob('./dependencies/antlr4Runtime/misc/*.cpp') + \
                                Glob('./dependencies/antlr4Runtime/support/.cpp') + \
                                Glob('./dependencies/antlr4Runtime/tree/*.cpp') + \
                                Glob('./dependencies/antlr4Runtime/tree/pattern/*.cpp') + \
                                Glob('./dependencies/antlr4Runtime/tree/xpath/*.cpp'),
                            CPPPATH = './dependencies/antlr4Runtime',
                            ARFLAGS = 'qc'
                          )

ParserFiles = env.Antlr(source='Coral.g4')

CoralLang = env.Program(target   = 'coral', 
                        source   = Glob('./src/*.cpp') + Glob('./src/Parser/*.cpp'), 
                        CPPPATH  = ['./src', './dependencies/antlr4Runtime'],
                        LIBPATH  = '.',
                        LIBS     = 'antlr4-runtime'
                        )



Requires(ParserFiles, AntlrRuntime)
Depends(CoralLang, ParserFiles)

Clean(ParserFiles, Glob('./src/Parser/*'))

最后是main.cpp文件。如您所见,它没有任何内容,只有antlr运行时包含了,这足以看到错误。

#include <cstdio>
#include "antlr4-runtime.h"

int main(int argc, const char *argv[])
{
    if (!argv[1]) {
        printf("hey! pass at least a file to parse...");
        return 0;
    }
    else {
        printf("parsing %s\n", argv[1]);
    }

    return 1;
}

尝试以相对错误构建程序时,整个SCons的输出是这样的:

clang++ -o src/Parser/CoralParser.o -c -std=c++11 -stdlib=libc++ -Isrc -Idependencies/antlr4Runtime src/Parser/CoralParser.cpp
clang++ -o src/Parser/CoralBaseVisitor.o -c -std=c++11 -stdlib=libc++ -Isrc -Idependencies/antlr4Runtime src/Parser/CoralBaseVisitor.cpp
clang++ -o src/Parser/CoralListener.o -c -std=c++11 -stdlib=libc++ -Isrc -Idependencies/antlr4Runtime src/Parser/CoralListener.cpp
clang++ -o src/Parser/CoralVisitor.o -c -std=c++11 -stdlib=libc++ -Isrc -Idependencies/antlr4Runtime src/Parser/CoralVisitor.cpp
clang++ -o src/Parser/CoralBaseListener.o -c -std=c++11 -stdlib=libc++ -Isrc -Idependencies/antlr4Runtime src/Parser/CoralBaseListener.cpp
clang++ -o src/Parser/CoralLexer.o -c -std=c++11 -stdlib=libc++ -Isrc -Idependencies/antlr4Runtime src/Parser/CoralLexer.cpp
clang++ -o coral -stdlib=libc++ src/main.o src/Parser/CoralBaseListener.o src/Parser/CoralBaseVisitor.o src/Parser/CoralLexer.o src/Parser/CoralListener.o src/Parser/CoralParser.o src/Parser/CoralVisitor.o -L. -lantlr4-runtime
Undefined symbols for architecture x86_64:
  "Guid::Guid(unsigned short const*, bool)", referenced from:
      antlr4::atn::ATNDeserializer::deserialize(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&) in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::toUUID(unsigned short const*, unsigned long) in libantlr4-runtime.a(ATNDeserializer.o)
  "Guid::Guid(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      antlr4::atn::ATNDeserializer::ADDED_PRECEDENCE_TRANSITIONS() in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::ADDED_LEXER_ACTIONS() in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::ADDED_UNICODE_SMP() in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::SERIALIZED_UUID() in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::BASE_SERIALIZED_UUID() in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::SUPPORTED_UUIDS() in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::deserialize(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&) in libantlr4-runtime.a(ATNDeserializer.o)
      ...
  "Guid::Guid(Guid const&)", referenced from:
      antlr4::atn::ATNDeserializer::SUPPORTED_UUIDS() in libantlr4-runtime.a(ATNDeserializer.o)
  "antlr4::ANTLRErrorListener::~ANTLRErrorListener()", referenced from:
      antlr4::Recognizer::Recognizer() in libantlr4-runtime.a(Recognizer.o)
      antlr4::Recognizer::~Recognizer() in libantlr4-runtime.a(Recognizer.o)
      antlr4::ProxyErrorListener::~ProxyErrorListener() in libantlr4-runtime.a(ProxyErrorListener.o)
      antlr4::ProxyErrorListener::~ProxyErrorListener() in libantlr4-runtime.a(ProxyErrorListener.o)
      antlr4::ConsoleErrorListener::~ConsoleErrorListener() in libantlr4-runtime.a(ConsoleErrorListener.o)
      antlr4::ConsoleErrorListener::~ConsoleErrorListener() in libantlr4-runtime.a(ConsoleErrorListener.o)
      antlr4::BaseErrorListener::~BaseErrorListener() in libantlr4-runtime.a(BaseErrorListener.o)
      ...
  "antlrcpp::replaceAll(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      antlr4::Recognizer::getTokenErrorDisplay(antlr4::Token*) in libantlr4-runtime.a(Recognizer.o)
      antlr4::DefaultErrorStrategy::escapeWSAndQuote(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const in libantlr4-runtime.a(DefaultErrorStrategy.o)
      antlr4::CommonToken::toString(antlr4::Recognizer*) const in libantlr4-runtime.a(CommonToken.o)
  "antlrcpp::arrayToString(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)", referenced from:
      antlr4::ParserRuleContext::toInfoString(antlr4::Parser*) in libantlr4-runtime.a(ParserRuleContext.o)
  "antlrcpp::escapeWhitespace(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool)", referenced from:
      antlr4::LexerNoViableAltException::toString() in libantlr4-runtime.a(LexerNoViableAltException.o)
      antlr4::tree::Trees::toStringTree(antlr4::tree::ParseTree*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, bool) in libantlr4-runtime.a(Trees.o)
  "antlrcpp::SingleWriteMultipleReadLock::readUnlock()", referenced from:
      antlr4::atn::LexerATNSimulator::getExistingTargetState(antlr4::dfa::DFAState*, unsigned long) in libantlr4-runtime.a(LexerATNSimulator.o)
      antlr4::atn::ParserATNSimulator::getExistingTargetState(antlr4::dfa::DFAState*, unsigned long) in libantlr4-runtime.a(ParserATNSimulator.o)
  "antlrcpp::SingleWriteMultipleReadLock::writeUnlock()", referenced from:
      antlr4::atn::LexerATNSimulator::addDFAEdge(antlr4::dfa::DFAState*, unsigned long, antlr4::dfa::DFAState*) in libantlr4-runtime.a(LexerATNSimulator.o)
      antlr4::atn::LexerATNSimulator::addDFAState(antlr4::atn::ATNConfigSet*) in libantlr4-runtime.a(LexerATNSimulator.o)
      antlr4::atn::ParserATNSimulator::adaptivePredict(antlr4::TokenStream*, unsigned long, antlr4::ParserRuleContext*) in libantlr4-runtime.a(ParserATNSimulator.o)
      antlr4::atn::ParserATNSimulator::addDFAEdge(antlr4::dfa::DFA&, antlr4::dfa::DFAState*, long, antlr4::dfa::DFAState*) in libantlr4-runtime.a(ParserATNSimulator.o)
      antlr4::dfa::DFA::setPrecedenceStartState(int, antlr4::dfa::DFAState*, antlrcpp::SingleWriteMultipleReadLock&) in libantlr4-runtime.a(DFA.o)
  "antlrcpp::SingleWriteMultipleReadLock::readLock()", referenced from:
      antlr4::atn::LexerATNSimulator::getExistingTargetState(antlr4::dfa::DFAState*, unsigned long) in libantlr4-runtime.a(LexerATNSimulator.o)
      antlr4::atn::ParserATNSimulator::getExistingTargetState(antlr4::dfa::DFAState*, unsigned long) in libantlr4-runtime.a(ParserATNSimulator.o)
  "antlrcpp::SingleWriteMultipleReadLock::writeLock()", referenced from:
      antlr4::atn::LexerATNSimulator::addDFAEdge(antlr4::dfa::DFAState*, unsigned long, antlr4::dfa::DFAState*) in libantlr4-runtime.a(LexerATNSimulator.o)
      antlr4::atn::LexerATNSimulator::addDFAState(antlr4::atn::ATNConfigSet*) in libantlr4-runtime.a(LexerATNSimulator.o)
      antlr4::atn::ParserATNSimulator::adaptivePredict(antlr4::TokenStream*, unsigned long, antlr4::ParserRuleContext*) in libantlr4-runtime.a(ParserATNSimulator.o)
      antlr4::atn::ParserATNSimulator::addDFAEdge(antlr4::dfa::DFA&, antlr4::dfa::DFAState*, long, antlr4::dfa::DFAState*) in libantlr4-runtime.a(ParserATNSimulator.o)
      antlr4::dfa::DFA::setPrecedenceStartState(int, antlr4::dfa::DFAState*, antlrcpp::SingleWriteMultipleReadLock&) in libantlr4-runtime.a(DFA.o)
  "antlrcpp::toMap(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)", referenced from:
      antlr4::Recognizer::getRuleIndexMap() in libantlr4-runtime.a(Recognizer.o)
  "antlrcpp::indent(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)", referenced from:
      antlr4::atn::ATN::toString() const in libantlr4-runtime.a(ATN.o)
  "antlrcpp::finally(std::__1::function<void ()>)", referenced from:
      Coral::CoralParser::unit() in CoralParser.o
      Coral::CoralParser::assignment() in CoralParser.o
      Coral::CoralParser::variable() in CoralParser.o
      Coral::CoralParser::number() in CoralParser.o
      Coral::CoralParser::expression(int) in CoralParser.o
      antlr4::atn::LexerATNSimulator::match(antlr4::CharStream*, unsigned long) in libantlr4-runtime.a(LexerATNSimulator.o)
      antlr4::atn::LexerATNSimulator::evaluatePredicate(antlr4::CharStream*, unsigned long, unsigned long, bool) in libantlr4-runtime.a(LexerATNSimulator.o)
      ...
  "Guid::toString() const", referenced from:
      antlr4::atn::ATNDeserializer::deserialize(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&) in libantlr4-runtime.a(ATNDeserializer.o)
  "Guid::operator==(Guid const&) const", referenced from:
      antlr4::atn::ATNDeserializer::isFeatureSupported(Guid const&, Guid const&) in libantlr4-runtime.a(ATNDeserializer.o)
      antlr4::atn::ATNDeserializer::deserialize(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&) in libantlr4-runtime.a(ATNDeserializer.o)
  "typeinfo for antlr4::ANTLRErrorListener", referenced from:
      typeinfo for antlr4::ProxyErrorListener in libantlr4-runtime.a(ProxyErrorListener.o)
      typeinfo for antlr4::BaseErrorListener in libantlr4-runtime.a(BaseErrorListener.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我正在尝试创建一个SConstruct,将...将Antlr4 cpp运行时构建为静态库使用Antrl4(java应用程序)以简单的语法以cpp格式构建Lexer,Parser,Visitor和Listener。 ...

macos antlr4 clang++ scons .a
1个回答
0
投票

基于缺少的符号输出,您需要至少再添加一个库到LIBS。无论提供什么:

© www.soinside.com 2019 - 2024. All rights reserved.