order of imports for clang libraries - clang

I'm writing my own Makefile to compile my minimum standalone clang tool consisting of the following code:
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
static llvm::cl::OptionCategory ToolingSampleCategory("MetaLift Clang Frontend");
int main (int argc, const char **argv)
{
CommonOptionsParser op(argc, argv, ToolingSampleCategory);
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
return 0;
}
Is there a "proper" order to import the clang libraries? My current order is:
-lclangTooling -lclangSerialization -lclangFrontend
But I keep running into undefined symbols issues.

I find using CMake to be the easiest way to build a libTooling-based application. Here is a minimalistic snippet to compile your example:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
# Find CMake file for Clang
find_package(Clang REQUIRED)
# Add path to LLVM modules
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${LLVM_CMAKE_DIR}"
)
# import LLVM CMake functions
include(AddLLVM)
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${CLANG_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
add_definitions(${CLANG_DEFINITIONS})
add_llvm_executable(myTool main.cpp)
set_property(TARGET myTool PROPERTY CXX_STANDARD 11)
target_link_libraries(myTool PRIVATE clangTooling)
// main.cpp
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
static llvm::cl::OptionCategory
ToolingSampleCategory("MetaLift Clang Frontend");
int main(int argc, const char **argv) {
CommonOptionsParser op(argc, argv, ToolingSampleCategory);
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
return 0;
}
I checked the actual commands happening during the build:
c++ -DGTEST_HAS_RTTI=0 -I${CLANG}/include -O3 -DNDEBUG -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -fno-exceptions -fno-rtti -std=gnu++11 -o CMakeFiles/myTool.dir/main.cpp.o -c /Users/vsavchenko/source/c++/clang-makefile/main.cpp
c++ -O3 -DNDEBUG -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names -Wl,-dead_strip CMakeFiles/myTool.dir/main.cpp.o -o myTool -Wl,-rpath,#loader_path/../lib -Wl,-rpath,${CLANG}/lib ${CLANG}/lib/libclangTooling.a ${CLANG}/lib/libclangASTMatchers.a ${CLANG}/lib/libclangFormat.a ${CLANG}/lib/libclangFrontend.a ${CLANG}/lib/libclangDriver.a ${CLANG}/lib/libclangParse.a ${CLANG}/lib/libLLVMMCParser.a ${CLANG}/lib/libclangSerialization.a ${CLANG}/lib/libclangSema.a ${CLANG}/lib/libclangEdit.a ${CLANG}/lib/libclangAnalysis.a ${CLANG}/lib/libLLVMBitReader.a ${CLANG}/lib/libLLVMProfileData.a ${CLANG}/lib/libclangToolingCore.a ${CLANG}/lib/libclangAST.a ${CLANG}/lib/libclangRewrite.a ${CLANG}/lib/libclangLex.a ${CLANG}/lib/libclangBasic.a ${CLANG}/lib/libLLVMCore.a ${CLANG}/lib/libLLVMBinaryFormat.a ${CLANG}/lib/libLLVMMC.a ${CLANG}/lib/libLLVMOption.a ${CLANG}/lib/libLLVMSupport.a -lz -lcurses -lm /Users/vsavchenko/bin/clang/lib/libLLVMDemangle.a
It looks like the problem is not with the order of Clang libraries, but rather an insufficient set of them. The following command finishes without linking errors:
LIBRARY_PATH=${CLANG}/lib clang++ -std=c++11 -lclangTooling -lclangASTMatchers -lclangFormat -lclangFrontend -lclangDriver -lclangParse -lLLVMMCParser -lclangSerialization -lclangSema -lclangEdit -lclangAnalysis -lLLVMBitReader -lLLVMProfileData -lclangToolingCore -lclangAST -lclangRewrite -lclangLex -lclangBasic -lLLVMCore -lLLVMBinaryFormat -lLLVMMC -lLLVMOption -lLLVMSupport -lz -lcurses -lLLVMDemangle -I${CLANG}/include main.cpp
Happy hacking with Clang!

Related

ClangTool parse code short-circuit evaluation can't work when Macro preprocess

I used ClangTool to develop a code generate tool, but I found Clang code parser can't preprocess macro with short-circuit evaluation.
Here is the minimal reproducible code
#include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Tooling/Tooling.h>
#include <gtest/gtest.h>
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace clang;
using namespace llvm::cl;
const char *simpleCode = R"(
#if defined(__MINGW32__)
class A {B}
#endif
#if defined(__MINGW32__) && __has_include(<pthread.h>)
class C {D}
#endif
class X {};
)";
TEST(runToolOnCode, CanSyntaxCheckCode)
{
EXPECT_TRUE(runToolOnCode(std::make_unique<clang::SyntaxOnlyAction>(), simpleCode));
}
I expect to be able to parse correctly, but I got
input.cc:5:43: fatal error: cannot open file '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/pthread.h': No such file or directory
Running main() from /Volumes/Demon/Demo/Polaris/cmake-build-debug/_deps/googletest-src/googletest/src/gtest_main.cc
#if defined(__MINGW32__) && __has_include(<pthread.h>)
^
1 error generated.
/Volumes/Demon/Demo/Polaris/tests/hello.cpp:28: Failure
Value of: runToolOnCode(std::make_unique<clang::SyntaxOnlyAction>(), simpleCode)
Actual: false
Expected: true
About my environment
MaxOSX 11.3.1
XCode 12.5.1
➜ ~ clang++ -E -x c++ - -v
Homebrew clang version 12.0.0
Target: x86_64-apple-darwin20.4.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin
(in-process)
"/usr/local/Cellar/llvm/12.0.0_1/bin/clang-12" -cc1 -triple x86_64-apple-macosx11.0.0 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -E -disable-free -disable-llvm-verifier -discard-value-names -main-file-name - -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fno-rounding-math -munwind-tables -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -target-cpu penryn -tune-cpu generic -debugger-tuning=lldb -target-linker-version 650.9 -v -resource-dir /usr/local/Cellar/llvm/12.0.0_1/lib/clang/12.0.0 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -stdlib=libc++ -internal-isystem /usr/local/opt/llvm/bin/../include/c++/v1 -internal-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /usr/local/Cellar/llvm/12.0.0_1/lib/clang/12.0.0/include -internal-externc-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -fdeprecated-macro -fdebug-compilation-dir /Users/abao -ferror-limit 19 -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fmax-type-align=16 -fcolor-diagnostics -o - -x c++ -
clang -cc1 version 12.0.0 based upon LLVM 12.0.0 default target x86_64-apple-darwin20.4.0
ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/opt/llvm/bin/../include/c++/v1
/usr/local/Cellar/llvm/12.0.0_1/lib/clang/12.0.0/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.
use llvm 11.1.0 could circumvent this problem, this may be a bug in version 12.0.0

Linking to statically compiled z3 needs additional libraries on Linux

I used CMake to compile a static version of (a fairly recent of) z3 using:
cmake -DBUILD_LIBZ3_SHARED=false -DCMAKE_INSTALL_PREFIX=/opt/z3-devel -G "Unix Makefiles" ../
Now when I statically link the library against a C++ program, say this small variation of a z3 example:
#include"z3++.h"
using namespace z3;
int main(int argc, char** argv) {
config conf;
context c(conf);
expr x = c.int_const("x");
expr y = c.int_const("y");
expr z = c.int_const("z");
goal g(c);
g.add( ((2*x)+y)+z == 4);
g.add( (x+(2*y))+z == 4);
g.add( x+y == 4);
std::cout << g << "\n";
tactic t(c, "fm");
apply_result r = t(g);
std::cout << r << "\n";
return 0;
}
via
g++ -c -I /opt/z3-devel/include -static -o main.o main.cc
g++ -static -L /opt/z3-devel/lib64 -o main main.o -lz3
I receive a long list of undefined reference linking errors. What solves the issue is to add -lgomp -pthread -lrt -ldl as additional libraries. The linker outputs the following warning:
/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/8/libgomp.a(target.o): in function `gomp_target_init':
(.text+0x32c): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
Nevertheless, the program runs fine on my own machine and on Starexec.
Is this combination of static and dynamic linking the best I can do? Shouldn't those libraries be already statically linked into libz3.a? I have static versions of gomp, pthread and rt available on the system.

ESP8266 NONOS SDK: How to compile C++ code?

ESP8266 NONOS SDK: How to compile C++ code?
I'm somehow not able to compile C++ code using the ESP8266 NONOS SDK.
I use the gen_misc.sh-script to configure and compile the program,
but it outputs the following error:
start...
make[1]: Entering directory '/repos/esp/ESP8266_NONOS_SDK/diplomarbeit-firmware/user'
xtensa-lx106-elf-g++ -Os -g -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections -fno-builtin-printf -DICACHE_FLASH -DSPI_FLASH_SIZE_MAP=3 -I include -I ./ -I ../../include/ets -I ../include -I ../../include -I ../../include/eagle -I ../../driver_lib/include -o .output/eagle/debug/obj/user_main.o -c user_main.cpp
xtensa-lx106-elf-ar ru .output/eagle/debug/lib/libuser.a .output/eagle/debug/obj/user_main.o
make[1]: Leaving directory '/repos/esp/ESP8266_NONOS_SDK/diplomarbeit-firmware/user'
xtensa-lx106-elf-gcc -L../lib -nostdlib -T../ld/eagle.app.v6.ld -Wl,--no-check-sections -Wl,--gc-sections -u call_user_start -Wl,-static -Wl,--start-group -lc -lgcc -lhal -lphy -lpp-lnet80211 -llwip -lwpa -lcrypto -lmain -ldriver user/.output/eagle/debug/lib/libuser.a -Wl,--end-group -o .output/eagle/debug/image/eagle.app.v6.out
../lib/libmain.a(app_main.o): In function `user_uart_wait_tx_fifo_empty':
(.irom0.text+0x6a0): undefined reference to `user_pre_init'
../lib/libmain.a(app_main.o): In function `user_uart_wait_tx_fifo_empty':
(.irom0.text+0x6b8): undefined reference to `user_init'
../lib/libmain.a(app_main.o): In function `flash_data_check':
(.irom0.text+0x718): undefined reference to `user_pre_init'
../lib/libmain.a(app_main.o): In function `flash_data_check':
(.irom0.text+0xac1): undefined reference to `user_init'
collect2: error: ld returned 1 exit status
../Makefile:398: recipe for target '.output/eagle/debug/image/eagle.app.v6.out' failed
make: *** [.output/eagle/debug/image/eagle.app.v6.out] Error 1
My code looks like that:
user_main.cpp
#include "user_interface.h"
#include "osapi.h"
#include "partition.h"
void ICACHE_FLASH_ATTR user_pre_init ()
{
// register partition table here
if (!system_partition_table_regist(partition_table,
sizeof(partition_table) / sizeof(partition_table[0]),
SPI_FLASH_SIZE_MAP))
{
os_printf("FAIL TO REGISTER PARTITION TABLE");
while (1) {}
}
}
class MyClass {
};
void user_init ()
{
os_printf("Hello world!\n");
}
I really don't know how to fix this problem.
The header files you are including are C header files, not C++. The C++ compiler will mangle the function names, leading to the above error you see. You need to wrap them in an extern block like this to tell the compiler not to mangle them:
extern "C" {
#include "user_interface.h"
#include "osapi.h"
#include "partition.h"
}

Glib linking error for g_socket_new

I am trying to learn glib and gObject for a networking project.
Here is the command used to compile (after using pkg-config to get output):
gcc socket1.c -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lgobject-2.0 -lglib-2.0
socket1.c, after stripping, to identify the problem is:
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <gio/gio.h>
static GSocket *mySocket;
int main(int argc, char **argv) {
GError *err1 = NULL;
mySocket = g_socket_new ( G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_TCP,
&err1);
}
The error is:
/tmp/ccKIEXOi.o: In function `main':
socket1.c:(.text+0x3d): undefined reference to `g_socket_new'
collect2: error: ld returned 1 exit status
I have tried to use readelf -Ws and nm to see if I could see g_new_socket in any of the .so files linked. I did not see any. Is there a separate library I need to link to? Where/which is it?
You need to link to libgio-2.0.so, which is the third part of GLib (GLib, GObject, GIO). You can get its compiler and linker flags from pkg-config using pkg-config --cflags --libs gio-2.0.
You can tell GSocket is in GIO by looking at the documentation — it’s in the GIO manual: https://developer.gnome.org/gio/stable/GSocket.html.

Is it possible code coverage of a shared library using gcov?

I try to test an executable which uses OpenCV shared library. When using gcov to know what code lines were covered I only get info about my .cpp files and .hpp of the library. No info is shown about .cpp files of the library.
I compiled and linked with -pg --coverage flags.
Yes, gcov can give coverage information about a shared library. If I remember correctly from the problems I had getting this to work on my project, you're probably not including the --coverage flag on the linking of the dynamic library. Here's the smallest example I could create.
Makefile:
CXXFLAGS += --coverage
LDFLAGS += --coverage
myexec: myexec.cpp libmylib.so
libmylib.so: mylib.o
gcc --coverage -shared -Wl,-soname,libmylib.so -o libmylib.so mylib.o
mylib.o: CXXFLAGS += -fPIC
myexec.cpp:
#include "mylib.h"
int main(int argc, char** argv)
{
return is_even(argc);
}
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
int is_even(int num);
#endif
mylib.cpp
#include "mylib.h"
int is_even(int num)
{
if (num % 2)
return false;
else
return true;
}
Output of make (so you can see exactly what the build was):
g++ --coverage -fPIC -c -o mylib.o mylib.cpp
gcc --coverage -shared -Wl,-soname,libmylib.so -o libmylib.so mylib.o
g++ --coverage --coverage myexec.cpp libmylib.so -o myexec
I ran the executable using LD_LIBRARY_PATH="." ./myexec a, and then ran gcov mylib.cpp. Here's the contents of mylib.cpp.gcov:
-: 0:Source:mylib.cpp
-: 0:Graph:mylib.gcno
-: 0:Data:mylib.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include "mylib.h"
-: 2:
1: 3:int is_even(int num)
-: 4:{
1: 5: if (num % 2)
#####: 6: return false;
-: 7: else
1: 8: return true;
-: 9:}

Resources