Static Compilation for wxWidgets C++ - c++

As a starter I would like to point out that I have spent few hours trying to resolve the problem with no success. I wrote a small project using wxWidgets library for C++ in Clion on Mac. Since majority of my classmates have done their projects in VisualStudio on Windows, nobody could help me out. The project must be handed in in a form of an executable which will work on any computer. I suppose that the solution I should be looking for is static compilation which would staticly link all of the libraries to the executable file. I tried adding some flags like the one below to the Cmake:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread")
but it did not help whatsoever. I have absolutely no knowledge on how CMake works and I would greatly appreciate any help.
The whole cmake file which I currently have:
cmake_minimum_required(VERSION 3.9)
project(Lab3)
set(EXECUTABLE_NAME "Indexer")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra -DWX_PRECOMP")
# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
find_package(wxWidgets COMPONENTS core base REQUIRED)
include(${wxWidgets_USE_FILE})
include_directories(include/ ${wxWidgets_INCLUDE_DIRS})
file(GLOB SOURCES "src/*.cpp")
add_executable(${PROJECT_NAME} main.cpp Source.cpp Source.h)
target_link_libraries(${PROJECT_NAME} ${wxWidgets_LIBRARIES})
EDIT: I guess I didn't specify the problem clearly enough. The program compiles fine- everything works. It's just that whenever I try to copy the executable file (the end application) to a different computer it just doesn't work or shows up as a text file with corrupted characters instead of an application with a GUI etc..

You're not copying the right thing across. What you believe to be the application is probably just some kind of launcher.
Mac GUI applications do not consist of just a single file. Your Indexer app is actually what Apple call a bundle. The Finder presents this to the user as a single entity but it's really a folder.
You can look inside a bundle by right-clicking on it (or Ctrl+click) and selecting Show package contents. If you want to understand a bit more about what's in there, Apple document it here.
A good way to get a bundle from A to B might be to ZIP it. Once you have done that you will find out whether your efforts to statically link it have been successful. What I don't know is where your build system has put it, but maybe this post will help. It will be called Indexer.app, maybe Spotlight can find it.

To build wxWidgets with as few dependencies as possible, you should configure it with not only --disable-shared, but also --disable-sys-libs, to prevent it from using any third party libraries (e.g. libz, libpng, ...) that might be installed on your system.
After building your application using wxWidgets, you should confirm that otool -L YourApp.app/Contents/MacOS/YourApp doesn't show any non-system libraries.

Related

X11 not being linked into static library

So I am building a tiny "game engine" in C++, using cmake to build it, and I am making it as a static library. In windows it works perfectly, but in linux I need to link X11.
Now this wouldn't be a problem, I can just add add_link_options(-lX11) in CMakeLists.txt, and mylib.a will build fine, but when I go and use my mylib.a, and link it into a C++ program, I also need to link X11 again using the add_link_options command.
I am trying to do something similar to what raylib does, and I also want to do linking and including the library how raylib does it (in raylib you only need to link libraylib.a, and everything else is taken care of), but in my case, every time I want to link mylib.a into a C++ project, I also need to link X11.
If I make mylib to be shared (mylib.so), it works without the need to link X11 in the second project as well, but I would like to have a static version of the library working as well.
Here's my CMakeLists.txt for my library:
cmake_minimum_required(VERSION 3.0.0)
project(ntt VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED TRUE)
add_link_options(-lX11)
# GLFW config (this one I copied from raylib directly)
set(BUILD_SHARED_LIBS OFF)
set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_DOCS OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_INSTALL OFF)
add_subdirectory("${CMAKE_SOURCE_DIR}/src/glfw")
add_compile_definitions(_GLFW_X11)
# Generate source list
file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/src/*.cpp")
list(APPEND SOURCES "${CMAKE_SOURCE_DIR}/src/glad/src/glad.c")
list(APPEND SOURCES $<TARGET_OBJECTS:glfw>)
# Create the library
add_library(ntt ${SOURCES})
set_target_properties(ntt PROPERTIES
PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/include/Engine.hpp"
)
# Add include directories
target_include_directories(
ntt
PUBLIC
"${CMAKE_SOURCE_DIR}/include"
PRIVATE
"${CMAKE_SOURCE_DIR}/src/glad/include"
"${CMAKE_SOURCE_DIR}/src/glfw/include"
)
And here's CMakeLists.txt for a project that uses my library, and doesn't work (unless I add the add_link_options(-lX11)):
cmake_minimum_required(VERSION 3.0.0)
project(TestCpp VERSION 0.1.0)
# I want to not need to have this line here
# add_link_options(-lX11)
add_executable(TestCpp main.cpp)
target_include_directories(TestCpp PUBLIC "${CMAKE_SOURCE_DIR}/include")
target_link_libraries(TestCpp PUBLIC "${CMAKE_SOURCE_DIR}/libntt.a")
When I try to build the second project I get a bunch of errors like this:
/usr/bin/ld: /media/hdd/Development/C-C++/test/libntt.a(x11_monitor.c.o): in function `_glfwPollMonitorsX11': x11_monitor.c:(.text+0x3e8): undefined reference to `XFree' (they all come from places like x11_window, or x11_monitor, and all of them are abount missing references to different X11 functions used by glfw)
I know I must be missing something really easy, but I just don't know what. I am not new to C++, but this is the first time I've made an actual proper library, and I'm also pretty new to cmake (so pls excuse bad practices you might see in my CMakeLists).
I mostly relied on Microsoft's Visual Studio build system until recently, and the only reason I switched to cmake was to be able to port my code to more than one platform(windows) without jumping through the weird hoops that VS makes you jump through when configuring the project, and now I'm starting to like it, but every once in a while I bump into something like this.
So, in short: X11 links properly with -lX11, but I would like to only have the user link my library, and not have to bother with also linking X11 manually.
With raylib you only need to do target_link_libraries(mytarget PUBLIC raylib.a) and that links X11 and opengl and everything else needed, but in my case you also need to add_link_options(-lX11), and I want to not have to do that.

Boost Installation in CLion

I am a complete beginner in C++ programming and have been advised to use CLion. I am trying to get the Boost package to work.
I found many posts and tutorials online, however they all skip the basics not known to someone who is not a programmer. Namely, there is no explanation of how to get from the moment you open a new project to using some function from the Boost package?
This is what I found to be lacking from previous answers:
Here we are advised to use live incboost live template, however there is no explanation on where to find it or how to use it.
Here seems like a clear tutorial, however it is aimed at Visual Studio, not CLion.
Here I am not sure what each of those files are and how to adjust them to match my case.
I have downloaded boost_1_70_0 from https://www.boost.org/users/download/ and it is now unzipped and saved in C:\...\boost_1_70_0.
Could someone please explain really simply how to get from a blank project to being able to use functions stored in boost?
Considering you are using CLion and it supports only CMake at this time and you have installed BOOST library in the default directory, then your CMakeLists.txt file should look like this. I have used it in linux operating system but it should be able in Windows too.
cmake_minimum_required(VERSION 3.13)
project(LaserCV)
set(CMAKE_CXX_STANDARD 17)
#local
file(GLOB SOURCES
*.hpp
*.cpp
)
add_executable(LaserCV ${SOURCE_FILES} ${SOURCES})
#add_executable(LaserCV main.cpp)
SET(CMAKE_CXX_FLAGS -pthread)
#boost
find_package(Boost REQUIRED)
target_link_libraries(LaserCV ${Boost_LIBRARIES})
include_directories(${Boost_INCLUDE_DIR})
Then simply include a header file for your wanted boost function, for example:
#include <boost/random.hpp>

How to configure libXML with CMake?

I have learned the basics of C++ programming and thought of ways how I could proceed, in order to practise. One thing that caught my interest was Web Scraping. Since I only knew BeautifulSoup, I searched for an alternative for C++ and found libXML for C++, however I'm trying to install it but don't seem to get it to work, since I barely have an idea on how to configure a CMake file. I'm using CLion as an IDE and Windows as my operating system, if it matters. My project folder is
C:\Users\Laurenz\Documents\Programming\untitled10
and the place where I've put the libXML library is
C:\Users\Laurenz\Documents\Programming\untitled10\libXML
however, I think the "main" directory is the one below (since it contains most of the Source files), but I'm not sure which of both I need to include.
C:\Users\Laurenz\Documents\Programming\untitled10\libXML\libxml++
I've searched around in the internet and found dozens of methods on how people include libraries, so I'm not sure which I need to use. What I currently have:
cmake_minimum_required(VERSION 3.6)
project(untitled10)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(untitled10 ${SOURCE_FILES})
set(CMAKE_PREFIX_PATH "C:\\Users\\Laurenz\\Documents\\Programming\\untitled10\\libXML\\libxml++")
find_package(LibXML++ REQUIRED)
include_directories(${LibXML++_INCLUDE_DIRS})
set(LIBS ${LIBS} ${LibXML++_LIBRARIES})
target_link_libraries(untitled10 ${LIBS})
However, I get the following error message:
Error:By not providing "FindLibXML++.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "LibXML++", but CMake did not find one.
Could not find a package configuration file provided by "LibXML++" with any of the following names:
LibXML++Config.cmake libxml++-config.cmake
Add the installation prefix of "LibXML++" to CMAKE_PREFIX_PATH or set "LibXML++_DIR" to a directory containing one of the above files. If "LibXML++" provides a separate development package or SDK, be sure it has been installed.
Could someone tell me how to properly configure LibXML? And maybe someone knows some resources where I can learn how CMake files work, because it confuses me a bit.
Thanks!

How can I use CLion (1.2.4) for a project involving Qt Creator?

Qt Creator makes GUI creation ridiculously easy, but I would rather use CLion for the coding part, and only use Qt Creator for the GUI editing.
Definitely possible!
I'm on a mac, so there are a few things that I do that won't work the exact same for other operating systems. They're small, simple things that a bit of google-fu should fix relatively painlessly.
Step 1: Create a Qt Creator Project
I'll be using a widgets application for this example. I'll get to other types of projects a little later.
One thing that I would highly recommend is to change the build directory (under the Projects tab on the sidebar) to a relative path instead of an absolute one, especially if this is going into GitHub or the likes. I changed it to ./QtBinDebug.
Oh, and remember to copy or otherwise save in a separate location the contents of main.cpp for later.
That's it for Qt. We should only need to use Qt Creator when editing our GUI from now on.
Step 2: Open the project up in CLion
CLion need to create a few files in order to be able to work with our project. Tell CLion to make a new project, but name the project the exact same as the one we made in Qt Creator, and point CLion at the same path. It should warn you about files already existing, just ignore it.
CLion will have very helpfully overwritten main.cpp. Put what you copied from QtCreator back in there.
Step 3: Call the right Makefile
Qt Creator will actually generate it's own makefile that will call qmake, and do a whole bunch of other magic. It's insane... I can replace my existing CMakeLists.txt with
cmake_minimum_required(VERSION 3.3)
project(WindowTest)
set(QT_BIN "${PROJECT_SOURCE_DIR}/QtBinDebug")
add_custom_target(qtMakeFile COMMAND make -C ${QT_BIN})
This will build the project perfectly fine! The only problem is that CLion
only supports CMake projects right now. The above CMakeLists gets around that by telling CMake to just call make on the right makefile, but the IDE itself doesn't know how to interpret our code......
Step 4: Find out where the Qt libraries are installed
I installed Qt via Homebrew and found the libraries I needed at /usr/local/Cellar/qt5/5.5.1_2/lib/cmake. If you told Homebrew to link the installation, /usr/local/opt/qt5/lib/cmake will also work, and has the added benefit of keeping your Qt version up to date without needing to change anything!
Step 5: Linking in the Qt Libraries for CLion
If you're like me, you'd rather use CLion when it autocompletes everything and doesn't throw red text everywhere.
We need to tell CLion where to look for the libraries it's missing. For a basic Widgets project, I needed Qt5Core and Qt5Widgets. To see what you'll need for sure, check the makefile Qt Creator generated. You should find what you need near the top in the LIBS macro.
For the linking, we're going to be using the find_package(...) and target_link_libraries(...) commands. While we could hard-code everything into these two commands, I thought breaking it up a little would be a good idea.
One other small detail is the header file that Qt Creator places in the build directory. For a skeleton widgets project, it's ui_mainwindow.h. We can tell CLion where to look with an include_directories(...) command.
My CMakeLists.txt:
cmake_minimum_required(VERSION 3.3)
project(WindowTest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
#Base QT directory
set(QT_PATH "/usr/local/opt/qt5")
#Build output path of your QT Creator project
set(QT_BIN "${PROJECT_SOURCE_DIR}/QtBinDebug")
#Qt5 paths
#Qt5 library path
set(QT5_LIB_DIR ${QT_PATH}/lib/cmake)
#Qt5 individual libraries
set(QT5_CORE ${QT_LIB_DIR}/Qt5Core)
set(QT5_WIDGETS ${QT_LIB_DIR}/Qt5Widgets)
set(QT5_GUI ${QT_LIB_DIR}/Qt5Gui)
#Libraries to link to. The :: is for convenience
set(QT_LIBRARIES Qt5::Core Qt5::Widgets Qt5::Gui)
#Libraries required. Probably the same as above minus the '::'. find_package() will be called on these
set(QT_LIBRARIES_REQUIRED Qt5Core Qt5Widgets Qt5Gui)
#find packages
foreach(QT_LIBRARIES_REQUIRED ${QT_LIBRARIES_REQUIRED})
find_package( ${QT_LIBRARIES_REQUIRED} REQUIRED )
endforeach()
add_custom_target(qtMakefile COMMAND make -C ${QT_BIN})
include_directories(${QT_BIN})
set(SOURCE_FILES main.cpp mainwindow.cpp mainwindow.h mainwindow.ui)
add_executable(WindowTest ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
Step 6: Setting up CLion to actually run the thing properly
There should be a configuration that popped up in the run configurations menu. For me, with the above CMake file, it's qtMakefile. We need to do one last thing with that target, so click "Edit configurations..."
We need to select the executable that CLion should run after building. In the section for Executable, click "Select other..." and select the widget's executable. Mine was in QtBinDebug/WindowTest.app/Contents/MacOS/WindowTest.
And that's it! Congratulations!
Downsides
Debugging doesn't work. The debugger isn't linking on a simple hello world I put into my test program. To be honest, though, I really don't want to go down that rabbit hole.
Upsides
Autocomplete out the wazoo

Using Cmake, how do I prevent library sources from being included in my IDE?

Using a bunch of different libraries in my project (from GitHub sources, not precompiled), I add them to my target like this in my root CMakeLists.txt file:
add_subdirectory(lib/glew-1.13.0/build/cmake)
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/glew-1.13.0/include/)
...
target_link_libraries(MyApp glew ${GLEW_LIBRARIES} ... )
However, you can see from the screenshot below that Xcode includes all of the sources for those libraries in my project, which makes an insanely long list that I have to scroll through to find my code.
I have tried the EXCLUDE_FROM_ALL flag in the add_subdirectory command, which removes the library sources from my Xcode project, but then I cannot compile my project because Xcode doesn't compile the library at all.
Additionally, Xcode gives me tons of warnings from the libraries that I don't really care about. Using the SYSTEM flag with the include_directories command doesn't fix it.
What's the best way to solve this? Should I be compiling my libraries as a completely separate part of my build process rather than compiling them with my executable?
I'm not sure how it will work, but try this:
turn on the USE_FOLDERS in your root CMakeLists.txt
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
And then after you've added all the projects, set the FOLDER target property on all of the third party libraries:
set_property(TARGET target1 target2 ...
PROPERTY FOLDER "ThirdPartyLibs")
Being unfamiliar with C++, I thought that all of my libraries should be compiled along with my project every time. I ended up solving this by writing a shell script that precompiles all of my libraries once as static libraries, and now I don't have to worry about their sources in my IDE, plus I get faster compile times.