problems with highly specific cmake + qtCreator use case and unit tests - c++

My troubles with CMake keep compounding D:
What I have in mind is to create my project so that when I build it, it runs unit tests and if unit tests fail, it cleans up after itself. Otherwise, if they succeed, the build spits the runnable executable into the run/ directory.
My project directory contains subdirectories sources, headers, build, run, and tst/ut and thus far I have cmakelists at project root as well as inside sources and headers directories
CMakeLists.txt at the project root
project(TaskFour LANGUAGES CXX)
enable_testing()
set(BIN ${CMAKE_PROJECT_NAME})
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
add_library(${BIN}_lib)
add_executable(${BIN}_run)
include_directories(sources headers tst/ut)
cmakelists at sources/
set(SRC
main.cpp)
target_sources(${BIN} PUBLIC ${SRC})
and headers
#contents of this list are empty by design for now
set(SRC
"")
target_sources(${BIN} PUBLIC ${SRC})
With these CMake list files, QtCreator fails to see anything beyond the top-level CMake list file. It doesn't acknowledge the existence of the subdirectories in the project directory, the other two cmakeLists.txt files nor the main.cpp that very much exists inside the sources directory.
I have attempted to use the add_subdirectory command and that seemed to help as that made all the subdirectories show up. However, I quickly realized that QtCreator seemingly treated every subdirectory like its own project, and trying to add files into these newfangled "projects" resulted in a simple "failed to add one or more files to project foo" message.
I have understood that the point of CMake list files is to have several per project, each governing their own subsection of the larger project, and the top CMake list file gathering it all together. Before I did my CMake file as one big file at the root of the project, and I've understood that to not be good. I also understand that dividing headers and sources like I do is not exactly the most common practice but I hope you forgive me and help me get this thing working.
So, my actual question is, how do I do this? What am I currently doing wrong in my top-level cmakelists file to cause qtCreator to not find the files in the project? How do I write the CMake lists so that it would allow me to use the QTest framework, maybe even build the skeleton from QtCreator's project wizard (as currently the option to add the autotest project as a subproject is greyed out)?
Any insight is appreciated, and feel free to go into detail about CMake if you feel like it. This is an important piece of software development that I feel I've been missing out on.

There's a couple problems here with how you've organized your CMake file. This should at least get you started on the right path
You're calling add_library(${BIN}_lib) and add_executable(${BIN}_run) but then in your child CMake file you're calling target_sources(${BIN} ...) - target names are evaluated as strings - there is no target named BIN (or the value you set to BIN in this case), and adding sources to a target named BIN would not propagate those sources to targets named BIN_lib and BIN_run
include_directories is for adding entries to the C++ compiler's include search path, not for adding additional directories containing sources/other CMake files. For that, as you seem to have already figured out, you need add_subdirectories(...)

Related

Generating dll from an existing code on Windows using CMake and VS

I have downloaded an SDK written in C++ (OPC UA) that creates a .exe file on compiling with Visual Studio 2015. It has a bunch of CMake files. How could one see if it is possible to generate a .dll from such an SDK? Do the CMake files have this information or should there be any macros inside the headers I would have to search for ? The SDK has Visual Studio sample projects (.sln) that I am using to create .exe.
The CMakeLists.txt looks like this
project(uasdk)
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
include(CMakeDependentOption)
include(MessageUtils)
display_project_header("true")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src")
add_subdirectory(src)
endif ()
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples")
add_subdirectory(examples)
endif ()
# set CMAKE_INSTALL_MESSAGE to LAZY by default to hide 'Up to date' output when building INSTALL target
if (NOT ${CMAKE_VERSION} VERSION_LESS "3.1")
set(CMAKE_INSTALL_MESSAGE LAZY CACHE STRING "")
set(CMAKE_INSTALL_MESSAGE_VALUES "ALWAYS;LAZY;NEVER")
set_property(CACHE CMAKE_INSTALL_MESSAGE PROPERTY STRINGS ${CMAKE_INSTALL_MESSAGE_VALUES})
endif ()
The questions that already have been asked regarding this topic are from the people who are writing their own code. I intend to use the code from the SDK. Apart from changing the CMAKE file to include the dll do I need to make changes in the source code as well?
It has a bunch of CMake files. How could one see if it is possible to generate a .dll from such an SDK? Do, the CMake files have this information or should there be any MACROS inside the headers I would have to search for ?
If the CMake project generates a library, then the statement add_library must appear somewhere. Note, however, that hierarchies of CMakeLists.txt files are possible, for example, the CMakeLists.txt you included adds two subdirectories. Consider the CMakeLists.txt files in there as well. Since an executable is generated, a call to add_executable must appear somewhere as well.
I intend to use the code from the SDK. Apart from changing the CMAKE file to include the dll do I need to make changes in the source code as well?
I am not familiar with this SDK, but I would guess that examples contains the sources for the executable and src contains the sources for a library. If you just want to try something out, you can modify the example code or add a new example. In this case, you only have to modify the CMakeLists.txt in the examples directory (i.e., add your new source code file).
If you want to use the SDK as external dependency, check whether there is a FindNameofmySDK.cmake included in the CMake modules list or whether there is a NameofmySDK-config.cmake somewhere in the SDK sources or your installation. In this case, you can create a CMake project for your application and use find_package to look for the SDK.

Qt, CMake and Visual Studio Behavior

I'm porting some of my Qt projects into CMake to make them more flexible across different IDE's.
The only sad part with CMake, when I generate VS solution, it won't work amazingly as it works with the Qt VS Extension.
For example if I change a .ui file, I'll need to rebuild the project in order to see the changes in the GUI in comparison to when I use the VS Extension generated project, it will identify the changes automatically and re-moc the class that owns the .ui file without having to re-build the whole project.
If I look at the project configuration the VS Extension generates in the .vcxproj file, it would add ItemDefinitionGroup some items as follows:
And each class/file that is included in the project, will be flagged according to the type of the class(QtMoc, QtUic, QtRcc):
Probably this what gives the Qt VS Extension to identify how to treat each file, so if it's QtUic, then it would check if any changes in the .ui files are present, and if there are new changes, it would re-compile the ui file, then moc the class that belongs to the .ui file and only then re-compile the actual class that owns the .ui file.
In summary, is there any possible way to make CMake generate a project similar to one Qt VS Extension generated when I choose in CMake the VS generator?
I'm guessing CMake doesn't support this internally, as they tend to abstract all this behavior to make all VS projects as generic as possible no matter what framework is used, but CMake does have flags to support Qt like:
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
So I'm assuming it wouldn't be much of a work to implement.
Probably my best bet is to fork CMake and re-implement this behavior myself?
psuedo example:
if CMAKE_AUTOMOC == ON & CMAKE_VS_EXT == ON
Do some custom changes to the .vcxproj file
endif
Sorry for the long post, but any ideas and help would be greatly appreciated. Thanks!
As it's too much (code) for a comment I put that an answer.
AFAIK you do not have to include the generated files to your add_executable call. That is something CMake automoc feature does behind the scenes.
A typical sequence in our CMakeLists.txt files look as follows:
include_directories(${CMAKE_CURRENT_BINARY_DIR})
file(GLOB_RECURSE SOURCES sources/*.cpp)
file(GLOB_RECURSE HEADERS include/*.h)
file(GLOB_RECURSE FORMS ui/*.ui)
set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui)
file(GLOB_RECURSE RESOURCES resources/*.qrc)
set(CMAKE_AUTOMOC TRUE)
set(CMAKE_AUTOUIC TRUE)
set(CMAKE_AUTORCC TRUE)
add_library(theLib ${SOURCES} ${HEADERS} ${FORMS} ${RESOURCES})
target_include_directories(theLib BEFORE
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
)

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!

CMake: 'AUTOMOC' feature skips sources of executable targets?

There is a medium-sized project with a top level CMakeLists.txt which defines some common stuff and invokes the configuration of all artifacts (subprojects) in the project like this:
add_subdirectory(components/A)
add_subdirectory(components/B)
add_subdirectory(components/C)
add_subdirectory(components/E)
Artifacts are static/shared libraries or executables (which somehow depend on each other). In this example, there is only one executable: E. Everything configures and builds perfectly fine when plain old qt4_wrap_cpp is used to process MOC.
When switching to the (relatively) new AUTOMOC feature by adding the following to the top CMakeLists.txt:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
all the sources of static/shared libraries are AUTOMOC'ed just fine. However, the sources of executable target (E in this example) are never AUTOMOC'ed.
I've tried both MSYS Makefiles and Ninja generators, and both simply do not create the target for AUTOMOC'ing, but only for executable's sources (for static/shared library targets AUTOMOC'ing target is added).
Has anyone experienced that already?
What could be the cause?
Does that smell like a bug?
Update
I found the cause, the discussion is on CMake mailing list.
To summarize, the problem was that E didn't include Qt module neither explicitly:
find_package(Qt4 ...)
nor implicitly:
find_package(MyPrecious ...)
where MyPrecious could be some 3rd party module which includes Qt by itself.
As a result, non-cached variables like QT_VERSION_* are not present in the scope of E subproject, and for that reason AUTOMOC feature cannot function properly. Nasty pitfall I'd say. For more details refer to CMake mailing list.

Working with Multiple Projects in CMake

I am currently working on transitioning over a Visual C++ project (that has multiple subprojects inside of it) over to CMake.
There is one thing that I am not sure about – basically, to include the subprojects from the top level CMakeLists.txt file, I just utilize the add_subdirectory command, and reference the directories that these various subprojects are stored under.
However, I have one project that is in the same directory as my top level CMakeLists.txt file, and so I am wondering if it is still possible to include this file somehow? CMake does not allow me to call add_subdirectory on the existing PROJECT_BINARY_DIR (see below):
add_subdirectory(${PROJECT_BINARY_DIR}) #not allowed in CMake
I cannot think of another way for me to include this subproject into my CMake build. Any ideas?
All add_subdirectory does is add a subdirectory with a CMakeLists.txt file in it, and so it would not make sense to allow you to add the current directory. You can simply add the CMake logic to build that part of your project in the CMakeLists.txt file. If you would like to separate the logic, then you could put it in build_project.cmake, and then use include,
include(build_project.cmake)
You can include as many other CMake files as you like, and that CMake code will be evaluated as if it was pasted inline. So all the normal add_executable and similar commands would work.