【发布时间】:2023-03-19 11:08:01
【问题描述】:
我正在处理一个相当大的项目的某些部分,该项目涉及在 C++ 上使用 GraphViz,但我似乎无法使用 GraphViz 函数。我的代码旨在自动从.dot 文件生成.png,但是当我尝试编译它时,我不断收到对'functionName'(与gvc.h 相关的所有函数)的“未定义引用”。我高度怀疑在编译过程中没有链接,但我不知道如何处理CMakeLists.txt 以及我应该首先链接什么。但是,我确实注意到我的/usr/include/graphviz 文件夹中有一个gv.cpp 文件,但我不知道我是否应该以某种方式链接该文件,或者它是否完全不同。
/usr/bin/ld: CMakeFiles/ag_gen.dir/src/main.cpp.o: in function `save_image_gv(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
main.cpp:(.text+0xf07): undefined reference to `gvContext'
/usr/bin/ld: main.cpp:(.text+0xf27): undefined reference to `agread'
/usr/bin/ld: main.cpp:(.text+0xf3c): undefined reference to `gvLayout'
/usr/bin/ld: main.cpp:(.text+0xfc8): undefined reference to `gvRender'
/usr/bin/ld: main.cpp:(.text+0xfef): undefined reference to `gvFreeLayout'
/usr/bin/ld: main.cpp:(.text+0xff7): undefined reference to `agclose'
/usr/bin/ld: main.cpp:(.text+0xfff): undefined reference to `gvFreeContext'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/ag_gen.dir/build.make:460: ag_gen] Error 1
make[2]: *** [CMakeFiles/Makefile2:156: CMakeFiles/ag_gen.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:163: CMakeFiles/ag_gen.dir/rule] Error 2
make: *** [Makefile:164: ag_gen] Error 2
这是我在 main.cpp 中的代码有问题的部分:
#include <graphviz/gvc.h>
bool save_image_gv(std::string filename){
GVC_t *gvc;
Agraph_t *g;
FILE *fp;
gvc = gvContext();
fp = fopen((filename).c_str(), "r");
g = agread(fp, 0);
gvLayout(gvc, g, "dot");
gvRender(gvc, g, "png", fopen((filename+".png").c_str(), "w"));
gvFreeLayout(gvc, g);
agclose(g);
return (gvFreeContext(gvc));
}
这是我的 CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
# Uncomment for gcc
# set(CMAKE_C_COMPILER "gcc-8")
# set(CMAKE_CXX_COMPILER "g++-8")
project(ag_gen)
set_source_files_properties(
mem.c
PROPERTIES
COMPILE_DEFINITIONS UNIT_TEST=1
)
# Common compiler options among built types
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
# Specific compiler options for Debug or Release builds
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 -ggdb -Wall -fopenmp -pedantic")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g -Wall -fopenmp -pedantic -O1")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1 -fopenmp")
set(PostgreSQL_TYPE_INCLUDE_DIR "9.5")
set(PostgreSQL_ADDITIONAL_VERSIONS "10.1" "10" "9.5")
find_program(LSB_RELEASE lsb_release)
execute_process(COMMAND ${LSB_RELEASE} -is
OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
include_directories("/usr/include/postgresql")
# Apple has a different openssl directory when using brew
if(APPLE)
set(BISON_EXECUTABLE "/usr/local/opt/bison/bin/bison")
set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl")
endif()
set(ENV{PKG_CONFIG_PATH} "/usr/local/lib/pkgconfig")
find_package(PkgConfig REQUIRED)
find_package(PostgreSQL REQUIRED)
find_package(OpenMP)
find_package(BISON 2.4 REQUIRED)
find_package(FLEX REQUIRED)
find_package(Boost REQUIRED)
find_package(OpenSSL)
find_package(Doxygen)
pkg_check_modules(CMOCKA cmocka)
pkg_check_modules(CPPREDIS cpp_redis)
if(OpenSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
# Enable thread-level parallelization if OpenMP is found.
if(OpenMP_CXX_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
if(DOXYGEN_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
endif(DOXYGEN_FOUND)
include_directories("${CMAKE_SOURCE_DIR}/src/")
file(GLOB ag_gen_src "${CMAKE_SOURCE_DIR}/src/ag_gen/*.cpp")
file(GLOB utils_src "${CMAKE_SOURCE_DIR}/src/util/*.c" "${CMAKE_SOURCE_DIR}/src/util/*.cpp")
########################
### Network Model Parser
########################
BISON_TARGET(nm_parser "${CMAKE_SOURCE_DIR}/src/parser/nm-parser/nm_parser.yy"
"${CMAKE_CURRENT_BINARY_DIR}/nm_parser.c"
DEFINES_FILE "${CMAKE_CURRENT_BINARY_DIR}/nm_parser.tab.h")
FLEX_TARGET(nm_scanner "${CMAKE_SOURCE_DIR}/src/parser/nm-parser/nm_scanner.l"
"${CMAKE_CURRENT_BINARY_DIR}/nm_scanner.c"
COMPILE_FLAGS "-Pnm")
ADD_FLEX_BISON_DEPENDENCY(nm_scanner nm_parser)
#add_executable(nm_test ${FLEX_nm_scanner_OUTPUTS} ${BISON_nm_parser_OUTPUTS} ${utils_src})
#target_include_directories(nm_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_SOURCE_DIR}/src/compiler/nm-parser")
##########################
### Exploit Pattern Parser
##########################
BISON_TARGET(xp_parser "${CMAKE_SOURCE_DIR}/src/parser/xp-parser/xp_parser.yy"
"${CMAKE_CURRENT_BINARY_DIR}/xp_parser.c"
DEFINES_FILE "${CMAKE_CURRENT_BINARY_DIR}/xp_parser.tab.h")
FLEX_TARGET(xp_scanner "${CMAKE_SOURCE_DIR}/src/parser/xp-parser/xp_scanner.l"
"${CMAKE_CURRENT_BINARY_DIR}/xp_scanner.c"
COMPILE_FLAGS "-Pxp")
ADD_FLEX_BISON_DEPENDENCY(xp_scanner xp_parser)
#add_executable(xp_test ${FLEX_xp_scanner_OUTPUTS} ${BISON_xp_parser_OUTPUTS} ${utils_src})
#target_include_directories(xp_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_SOURCE_DIR}/src/compiler/xp-parser")
####################
### Main application
####################
add_executable(ag_gen "${CMAKE_SOURCE_DIR}/src/main.cpp"
${FLEX_nm_scanner_OUTPUTS} ${BISON_nm_parser_OUTPUTS}
${FLEX_xp_scanner_OUTPUTS} ${BISON_xp_parser_OUTPUTS}
${ag_gen_src} ${utils_src})
target_link_libraries(ag_gen ${PostgreSQL_LIBRARIES})
add_executable(decode "${CMAKE_SOURCE_DIR}/src/tools/decode.cpp"
${ag_gen_src} ${utils_src})
target_link_libraries(decode ${PostgreSQL_LIBRARIES})
if(CPPREDIS_FOUND)
#include_directories("${CPPREDIS_INCLUDE_DIRS}")
link_directories("${CPPREDIS_LIBRARY_DIRS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DREDIS")
target_link_libraries(ag_gen cpp_redis tacopie)
target_link_libraries(decode cpp_redis tacopie)
endif()
################
### Unit Testing
################
if(CMOCKA_FOUND)
add_executable(dynstr_test ${CMAKE_SOURCE_DIR}/src/util/mem.c ${CMAKE_SOURCE_DIR}/src/tests/mem_test.c)
target_link_libraries(dynstr_test ${CMOCKA_LIBRARIES})
endif()
# Files to be added to build directory
configure_file("config.ini" "config.ini" COPYONLY)
if(CPPREDIS_FOUND)
add_custom_command(TARGET ag_gen PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/redis_scripts $<TARGET_FILE_DIR:ag_gen>/redis_scripts)
endif()
【问题讨论】:
-
欢迎来到 Stack Overflow!您的 CMake 文件似乎没有在任何地方提及 graphviz。您是否尝试链接到 Graphviz 库?它应该位于
/usr/lib64/graphviz或类似... -
由于我对 CMake 还很陌生,所以在链接到像 Graphviz 这样的库时,我不知道从哪里开始。你能带领我走向正确的方向吗?在 /usr/lib64/graphviz 下查看产生了 libgvplugin_core.so、libgvplugin_core.so.6、libgvplugin_gdk.so 和其他类似文件等文件。我必须单独链接所有这些吗?