X11 Include Issues With c++ Via CLion On FreeBSD 11? - cmake

I'm using CMake on FreeBSD 11 within CLion and have the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(owm)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp owm.cpp owm.h)
add_executable(owm ${SOURCE_FILES})
set(LIBS ${LIBS})
find_package(X11 REQUIRED)
if (X11_FOUND)
include_directories(${X11_INCLUDE_DIR})
link_libraries(${X11_LIBRARIES})
endif(X11_FOUND)
file(GLOB MY_PUBLIC_HEADERS
"test/*"
)
file(COPY ${MY_PUBLIC_HEADERS} DESTINATION test)
Which seems to work fine, however when going to compile the project I get the following:
/usr/local/bin/cmake --build /home/cory/projects/owm/cmake-build-debug --target all -- -j 12
Scanning dependencies of target owm
[ 33%] Building CXX object CMakeFiles/owm.dir/owm.cpp.o
[ 66%] Linking CXX executable owm
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)':
/home/cory/projects/owm/owm.cpp:20: undefined reference to `XOpenDisplay'
/home/cory/projects/owm/owm.cpp:22: undefined reference to `XDisplayName'
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::owm(_XDisplay*)':
/home/cory/projects/owm/owm.cpp:31: undefined reference to `XInternAtom'
/home/cory/projects/owm/owm.cpp:32: undefined reference to `XInternAtom'
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::~owm()':
/home/cory/projects/owm/owm.cpp:37: undefined reference to `XCloseDisplay'
c++: error: linker command failed with exit code 1 (use -v to see invocation)
gmake[2]: *** [CMakeFiles/owm.dir/build.make:121: owm] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/owm.dir/all] Error 2
gmake: *** [Makefile:84: all] Error 2
I'm not certain if this is relevant but message(FATAL_ERROR ${X11_LIBRARIES}) returns:
/usr/local/lib/libSM.so/usr/local/lib/libICE.so/usr/local/lib/libX11.so/usr/local/lib/libXext.so
And message(FATAL_ERROR ${X11_INCLUDE_DIR}) returns:
/usr/local/include
Within the offending file I have:
#include "owm.h"
extern "C" {
#include <X11/Xlib.h>
#include <X11/Xutil.h>
}
#include <iostream>
#include <cstring>
#include <algorithm>
template <typename T>
T* CHECK_NOTNULL(T* t) {
if (t == NULL) {
}
return (t);
}
std::unique_ptr<owm> owm::Create(const std::string& display_str) {
const char* display_c_str = (display_str.empty() ? nullptr : display_str.c_str());
Display* display = XOpenDisplay(display_c_str);
if (display == nullptr) {
std::cout << "Failed to open X display " << XDisplayName(display_c_str);
return (nullptr);
}
return (std::unique_ptr<owm>(new owm(display)));
}
owm::owm(Display *display)
: _display(CHECK_NOTNULL(display)),
_root(DefaultRootWindow(_display)),
WM_PROTOCOLS(XInternAtom(_display, "WM_PROTOCOLS", false)),
WM_DELETE_WINDOW(XInternAtom(_display, "WM_DELETE_WINDOW", false)) {
}
owm::~owm() {
XCloseDisplay(_display);
}
void owm::Run() {
}

Command link_libraries affects only on futher executables/libraries. From documentation:
Specify libraries or flags to use when linking any targets created later in the current directory or below by commands such as add_executable() or add_library().
So you need to either:
use link_libraries before add_executable or
use target_link_libraries instead (this is preferred way)

Related

Cmake undefined reference to function hello() [duplicate]

I have a test file (just for the link test) where I overload the new/delete operators with my own malloc/free library called libxmalloc.a. But I keep getting "undefined reference to" error as following when linking the static library, even I change the order of test.o and -lxmalloc. But everything works well with other C programs linking this library. I'm so confused with this issue and appreciate any clue.
Error Msg:
g++ -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64 -c -o test.o test.cpp
g++ -m64 -O3 -L. -o demo test.o -lxmalloc
test.o: In function `operator new(unsigned long)':
test.cpp:(.text+0x1): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete(void*)':
test.cpp:(.text+0x11): undefined reference to `free(void*)'
test.o: In function `operator new[](unsigned long)':
test.cpp:(.text+0x21): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete[](void*)':
test.cpp:(.text+0x31): undefined reference to `free(void*)'
test.o: In function `main':
test.cpp:(.text.startup+0xc): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x19): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x24): undefined reference to `free(void*)'
test.cpp:(.text.startup+0x31): undefined reference to `free(void*)'
collect2: ld returned 1 exit status
make: *** [demo] Error 1
My test.cpp file:
#include <dual/xalloc.h>
#include <dual/xmalloc.h>
void*
operator new (size_t sz)
{
return malloc(sz);
}
void
operator delete (void *ptr)
{
free(ptr);
}
void*
operator new[] (size_t sz)
{
return malloc(sz);
}
void
operator delete[] (void *ptr)
{
free(ptr);
}
int
main(void)
{
int *iP = new int;
int *aP = new int[3];
delete iP;
delete[] aP;
return 0;
}
My Makefile:
CFLAGS += -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64
CXXFLAGS += -m64 -O3
LIBDIR += -L.
LIBS += -lxmalloc
all: demo
demo: test.o
$(CXX) $(CXXFLAGS) $(LIBDIR) -o demo test.o $(LIBS)
test.o: test.cpp
$(CXX) $(CFLAGS) -c -o $# $<
clean:
- rm -f *.o demo
But everything works well with other C programs linking this library.
Did you notice that C and C++ compilation create different symbol names on object file level? It's called 'name mangling'.
The (C++) linker would show undefined references as demangled symbols in the error message, which might confuse you. If you inspect your test.o file with nm -u you'll see that the referenced symbol names don't match with those provided in your library.
If you want to use functions linked in as externals that were compiled using the plain C compiler, you'll need their function declarations enclosed in an extern "C" {} block which suppresses C++ name mangling for everything declared or defined inside, e.g.:
extern "C"
{
#include <dual/xalloc.h>
#include <dual/xmalloc.h>
}
Even better, you might wrap your function declarations in your header files like this:
#if defined (__cplusplus)
extern "C" {
#endif
/*
* Put plain C function declarations here ...
*/
#if defined (__cplusplus)
}
#endif

G++ doesn't find CoInitializeEx (and several other functions)?

I'm trying to compile the following code
#include <iostream>
#include <windows.h>
#include <objbase.h>
int main (int argc, char** argv) {
HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr)) {
std::cout << "Initialized" << std::endl;
} else {
std::cout << "Failed" << std::endl;
}
CoUninitialize();
return 0;
}
but
g++ -o test -L"<dir>" -lOle32 <file>.cpp
# <dir> contains Ole32.Lib
always tells me that __imp_CoInitializeEx and __imp_CoUninitialize are undefined and -print-file-name=Ole32.Lib just return Ole32.Lib. If g++ doesn't find Ole32.Lib, maybe
g++ -c -o test.o <file>.cpp
ld -L"<dir>" -lOle32 -o test test.o
works. Now g++/ld actually finds CoInitializeEx and CoUninitialize, but the standard library seems to be missing and adding -static-libstdc++ or -lstdc++ or -llibstdc++ doesn't help either. So what am I missing? Why is g++ unable to find CoInitializeEx and CoUninitialize?
EDIT: I can definitely say that there is nothing wrong with my code, my header files and my library files, because I can compile the code using Visual Studios compiler:
cl /c /EHsc ^
/I"<...>\Microsoft Visual Studio 14.0\VC\include" ^
/I"<...>\Windows Kits\10\Include\<version>\ucrt" ^
/I"<...>\Windows Kits\10\Include\<version>\shared" ^
/I"<...>\Windows Kits\10\Include\<version>\um" ^
/Fotest.obj ^
main.cpp
link /nologo /machine:x64 /subsystem:console ^
/libpath:"<...>\Microsoft Visual Studio 14.0\VC\lib\amd64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\ucrt\x64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\um\x64" ^
/out:test.exe ^
test.obj Ole32.Lib

gtest: undefined reference to `operator+'

This is just an observation, but I don't understand where is the problem. I implement vector addition operator and everything is work pretty well in the main function. But when I tried to test it by Google Test I got the compilation error
In function `ZN15Basic_Dirs_Test8TestBodyEv':
C:/Users/home/Documents/clion/example/test/main.cpp:10: undefined reference
to `operator+(std::vector<int, std::allocator<int> > const&,
std::vector<int, std::allocator<int> > const&)'
It compiles, however, when I remove src/class.cpp file. Could you tell me how it works? :)
The code is below.
src/class.h
#ifndef EXAMPLE_CLASS_H
#define EXAMPLE_CLASS_H
#include <vector>
std::vector<int> operator+(const std::vector<int>& a, const std::vector<int>& b);
#endif //EXAMPLE_CLASS_H
src/class.cpp
#include "class.h"
std::vector<int> operator+(const std::vector<int>& a, const std::vector<int>& b) {
if (a.size() != b.size()) {
std::cerr << "vectors are not of the same size!\n";
exit(1);
}
std::vector<int> res(a.size());
for (unsigned i = 0; i < a.size(); ++i) {
res[i] = a[i] + b[i];
}
return res;
}
test/main.cpp
#include "class.h"
#include <gtest/gtest.h>
using namespace std;
TEST(Basic, Dirs) {
std::vector<int> a = {1, 1, 0};
std::vector<int> b = {2, 1, 0};
std::vector<int> c = a+b;
EXPECT_EQ(c[0], 3);
EXPECT_EQ(c[1], 2);
EXPECT_EQ(c[2], 0);
}
./CMakeLists
cmake_minimum_required(VERSION 3.7)
project(example)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES src/main.cpp src/class.cpp)
add_subdirectory(test)
add_executable(example ${SOURCE_FILES})
test/CMakeLists
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
add_subdirectory("../lib/googletest" "${CMAKE_CURRENT_BINARY_DIR}/gtest_build")
include_directories(../lib/googletest/googletest/include)
include_directories(../src/)
add_executable(runtest main.cpp)
target_link_libraries(runtest gtest gtest_main)
You forgot to link your runtest gtest executable against your example:
./CMakeLists
cmake_minimum_required(VERSION 3.7)
project(example)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES src/main.cpp src/class.cpp)
add_executable(example ${SOURCE_FILES})
add_subdirectory(test)
test/CMakeLists
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
add_subdirectory("../lib/googletest" "${CMAKE_CURRENT_BINARY_DIR}/gtest_build")
include_directories(../lib/googletest/googletest/include)
include_directories(../src/)
add_executable(runtest main.cpp)
target_link_libraries(runtest gtest gtest_main example)
Also not that it might be better to actually define your example as a shared library instead of executable (just remove the main function - you probably don't need it anyway):
add_library(example SHARED ${SOURCE_FILES})

How come this const. expression does not compile?

#include <iostream>
using namespace std;
int main()
{
constexpr double GetPi() {return 22.0/7;}
cout << GetPi() << endl;
}
No idea what is going on here. Please help me.
I've tried to compile this and even tried to re-format the code but it doesn't really help much. I thought this was the correct way you did things? What's going on here? It's a constant expression.
Here is the compilation error:
C:\Windows\system32\cmd.exe /C "C:/TDM-GCC-64/bin/mingw32-make.exe -j4` SHELL=cmd.exe -e -f Makefile"
"----------Building project:[ Constant_Expression - Debug ]----------"
mingw32-make.exe[1]: Entering directory 'C:/Program Files/CodeLite/CPP/Constants/Constant_Expression'
codelite-cc C:/TDM-GCC-64/bin/g++.exe -c "C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp" -g -O0 -std=c++11 -Wall -o ./Debug/main.cpp.o -I. -I.
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp: In function 'int main()':
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp:7:30: error: a function-definition is not allowed here before '{' token
constexpr double GetPi() {return 22.0/7;}
^
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp:8:19: error: 'GetPi' was not declared in this scope
cout << GetPi() << endl;
^
mingw32-make.exe[1]: *** [Debug/main.cpp.o] Error 1
Constant_Expression.mk:93: recipe for target 'Debug/main.cpp.o' failed
mingw32-make.exe[1]: Leaving directory 'C:/Program Files/CodeLite/CPP/Constants/Constant_Expression'
mingw32-make.exe: *** [All] Error 2
Makefile:4: recipe for target 'All' failed
3 errors, 0 warnings
In C++ you are not allowed to define a function inside another function. (unlike closures in javascript).
You have to define GetPI() outside the main() function
#include <iostream>
using namespace std;
constexpr double GetPi() {return 22.0/7;}
int main()
{
cout << GetPi() << endl;
}

What is missing in the CMakeLists.txt / my library installation?

I reduced my prog to the minimum just to show the pb: cmake does not complain, neither make (running Linux / libglew 1.5 / cmake 2.8.2). The program segfaults, and I have no clue why / which steps I should now make to solve the pb.
Source of render.cpp:
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/glext.h>
#ifndef WIN32
#include <GL/glx.h>
#endif
#include <iostream>
#include <assert.h>
using namespace std;
int main()
{
cout << "Before init" << endl;
GLenum err = glewInit();
cout << "After init" << endl;
if (err != GLEW_OK)
cout << "Initialization error" << endl;
else{
cout << "Successful init" << endl;
assert(glCreateShader);
GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
}
}
The content of CMakeList is:
cmake_minimum_required (VERSION 2.6)
project (render)
IF(CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -std=c++0x")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
# Some directory shortcuts
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/conf)
INCLUDE(FindOpenGL REQUIRED)
INCLUDE(FindGLEW REQUIRED)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${GLEW_INCLUDE_DIR})
message(${OPENGL_LIBRARIES})
message(${GLEW_INCLUDE_DIR})
message(${GLEW_LIBRARIES})
add_executable(render render.cpp)
target_link_libraries(render ${GLEW_LIBRARIES} ${OPENGL_LIBRARIES})
As mentioned, it compiles and segfaults at the call to glewInit(). I have no idea what to search for at this point..
Any help would be great,
Thanks
Might be useful to anyone, I solved it: using openGL, you need to create a context before being able to call glewInit(). This can be done using the SDL library (simplifies this task). Have a look at this tutorial.