2

我正在为 c++ cmake 可执行应用程序创建一个库。在这个库中,我希望能够调用 julia 函数,如本例所示。为此,我从此处下载了 Julia linux 二进制文件,其中包括可执行应用程序、共享对象文件和包含文件。然后我将 libjulia.so 链接到我的共享库,并包含 Julia 标头。

我已经使用如下所示的 CMake 完成了此操作:

######################################
##### External Include directories

include_directories(externals/Julia/include/julia/)

######################################
##### External Libraries

set(${PROJECT_NAME}_EXTERNAL_LIBRARIES
    externals/Julia/lib/libjulia.so
    externals/Julia/lib/julia/libLLVM-3.9.1.so

)

######################################
##### Shared library

add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SRCS} ${${PROJECT_NAME}_HDRS})
target_link_libraries(${PROJECT_NAME} ${${PROJECT_NAME}_EXTERNAL_LIBRARIES})


######################################
##### Static library

add_library(${PROJECT_NAME}_STATIC STATIC ${${PROJECT_NAME}_SRCS} ${${PROJECT_NAME}_HDRS})
target_link_libraries(${PROJECT_NAME}_STATIC ${${PROJECT_NAME}_EXTERNAL_LIBRARIES})



######################################
##### Tests

set(test_sources
tests/sampleTest.cpp
)

include(tests/externals/UnitTests/CMakeScripts/MakeTests.cmake)#location of MakeTests.cmake

MakeTests() #Sets the instructions to create the makefile which builds the tests

我认为一个潜在的问题是我只链接了 libjulia.so 和 libLLVM-3.9.1.so,但实际上 Julia/lib 目录中还有更多。我只链接了这两个,因为我首先尝试在不链接任何内容的情况下进行编译,并且我对函数有未定义的引用,所以我添加了 libJulia.so,然后我对以路径 libLLVM\ 开头的函数有未定义的引用,所以我添加了 libLLVM-3.9.1 。所以。然后它运行,但失败,错误显示在这个问题的底部。另一个潜在的问题是我使用 gcc 编译,而不是 clang,所以我不知道 LLVM 库是否可以工作。

作为参考,这是我的 MakeTests 函数。它创建一个可执行文件并将我的静态库和 gtest 库链接到它。

######################################
##### Get the path of the unit test external
set(DIR_OF_MAKETESTS_CMAKE ${CMAKE_CURRENT_LIST_DIR}) #The directory that this function is ran from
get_filename_component(UNIT_TEST_DIR ${DIR_OF_MAKETESTS_CMAKE} DIRECTORY) #get parent directory

function(MakeTests)

    ######################################
    ##### Set gtest compile options for gtest to match compile options of test subject
    ##### This is to prevent the MSVC runtime library running twice.
    ##### For example you do no want to compile the foo.lib with the Runtime library option: Multi-threaded (/MT)
    ##### and the test project with the option: Multi-threaded DLL (/MD).

    set(gtest_force_shared_crt ON CACHE BOOL "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE)
    set(gtest_disable_pthreads OFF CACHE BOOL "Disable uses of pthreads in gtest." FORCE)

    if(MINGW)
        set(gtest_disable_pthreads ON CACHE BOOL "Disable uses of pthreads in gtest." FORCE)
    endif()

    ######################################
    ###### Add Gtest to build
    if(TARGET gtest_main) #only if it's not already been added as a target before.
        MESSAGE(STATUS "Gtest allready added as target")
    else()
            MESSAGE(STATUS "Fetching Googletest framework.")
            add_subdirectory(
                ${UNIT_TEST_DIR}/externals/GoogleTest
                ${PROJECT_BINARY_DIR}/gooogletest
                )
    endif()

    ######################################
    ###### Include Gtest directories (the root location for #include paths)

    include_directories(${gtest_SOURCE_DIR}/include)

    ######################################
    ##### Create a list of names for the executables
    set(test_names)                     #make an empty list
    list(LENGTH test_sources len1)              #len1 is length of test_sources list
    math(EXPR len2 "${len1} - 1")               #len2 is len1 - 1
    foreach(val RANGE ${len2})              #for val = 0 to len2
        list(GET test_sources ${val} src)           #list(GET <list> <element index> <output variable>)
        get_filename_component(name ${src} NAME_WE)         #get the name compnent of src
        list(APPEND test_names ${name})                     #append the name to the list
    endforeach()

    ######################################
    ##### Create a list of files needed for the executables

    set(test_files
        ${${PROJECT_NAME}_SRCS}     #from the main project. The test executables will need these to compile
        ${${PROJECT_NAME}_HDRS}
    )

    ######################################
    ##### Loop over all the .cpp files and create separate executables

    foreach(val RANGE ${len2})              #for val = 0 to len2
      list(GET test_names ${val} name)          #name will change on every loop
      list(GET test_sources ${val} src)         #list(GET <list> <element index> <output variable>)
      add_executable("${name}" "${src}" "${test_files}")    #add_executable(<name> source1 [source2 ...])
    endforeach()

    ######################################
    ###### Link the libraries

    foreach(val RANGE ${len2})                              #for val = 0 to len2
        list(GET test_names ${val} name)                        #name will change on every loop
        add_dependencies(${name} ${PROJECT_NAME}_STATIC)                    #Make sure main project builds before the unit test executable is built
        message(STATUS " LINKING: ${PROJECT_NAME}_STATIC to ${name}")
        target_link_libraries(${name} gtest_main)                   #link gtest libraries
        target_link_libraries(${name} ${PROJECT_NAME}_STATIC)               #link all other libraies
    endforeach()

endfunction()

然后我正在运行的可执行文件是 sampleTest.exe。这是由 sampleTest.cpp 制作的,如下所示:

#include <gtest/gtest.h>
#include <julia.h>


TEST(all,main_temp)
{

    std::cout << "starting test" << std::endl;

    /* required: setup the Julia context */
     jl_init(NULL);

    /* run Julia commands */
    jl_eval_string("print(sqrt(2.0))");

    /* strongly recommended: notify Julia that the
         program is about to terminate. this allows
         Julia time to cleanup pending write requests
         and run all finalizers
    */
    jl_atexit_hook(0);

    ASSERT_EQ(1,1);

}

我的应用程序输出如下:

Running main() from gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from all
[ RUN      ] all.main_temp
starting test
1ThreadSanitizer: can't find longjmp buf
FATAL: ThreadSanitizer CHECK failed: ../../../../src/libsanitizer/tsan/tsan_interceptors.cc:423 "((0)) != (0)" (0x0, 0x0)
    #0 <null> <null> (libtsan.so.0+0x000000075193)
    #1 <null> <null> (libtsan.so.0+0x00000007519b)
    #2 __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) <null> (libtsan.so.0+0x000000079d13)
    #3 <null> <null> (libtsan.so.0+0x000000023faa)
    #4 siglongjmp <null> (libtsan.so.0+0x00000002541f)
    #5 restore_stack /buildworker/worker/package_linux64/build/src/task.c:193 (libjulia.so.0.6+0x000000058a27)
    #6 restore_stack /buildworker/worker/package_linux64/build/src/task.c:188 (libjulia.so.0.6+0x000000058a55)
    #7 <null> <null> (0x7ffc91494110)

为什么我会收到此错误?我应该如何设置我的 CMake,以便我可以运行 Julia 代码而不会出现这样的错误?

谢谢。

4

0 回答 0