Why does qmake put all object (.o) files to one directory? - c++

Let's say I have a Qt application where I have two classes with the same name in two different namespaces:
namespace namespace1
{
class SomeClass;
}
namespace namespace2
{
class SomeClass;
}
and I have a project directory structure according to it:
-->src/
-->namespace1/
-->someclass.cpp
-->namespace2/
-->someclass.cpp
When I compile the application with qmake, it puts all object (.o) files to one directory - so it creates someclass.o file first and then it rewrites it with the second someclass.o - which is a name collision so it is bad.
Why does qmake not take into account the directory structure of the source files and why does it not create something like namespace1_someclass.o and namespace2_someclass.o?
Yes, I can put my classes to one directory and name them namespace1_someclass.cpp and namespace2_someclass.cpp and there will be no name collisions, but this causes little inconvenience while looking at the source files in the project explorer in Qt Creator because when there are lot of source files in the project, it is much less readable than if there was the directory structure which I can expand or collapse.
One more extreme is to have the directory structure like this:
-->src/
-->namespace1/
-->namespace1_someclass.cpp
-->namespace2/
-->namespace2_someclass.cpp
which solves name collision but it redundantly duplicates the namespace names - and therefore again less readable.
Why does qmake not have at least an option to put the object files to the directory structure according to the source files? Do creators of Qt not see that this is an important feature?
And one more thing - you could recommend me to use cmake tool instead of qmake but I see the use of cmake much much much more difficult than qmake and qmake does its job excellent for me so far - except object files placement.

You can actually put object files alongside source files by using:
CONFIG += object_parallel_to_source
or
CONFIG += object_with_source
depending on your qmake version.
Source: https://wiki.qt.io/Undocumented_QMake#Config_features

Depending on what you are trying to build, you may be able to use the subdirs template in qmake to do this. You'll need to put a project file in each of your namespace directories, and in this you can specify different output directories for your object files.
-->src/main.pro
-->namespace1/n1.pro
-->someclass.cpp
-->namespace2/n2.pro
-->someclass.cpp
main.pro:
TEMPLATE = subdirs
SUBDIRS = namespace1 namespace2
n1.pro and n2.pro:
include("../common.pri")
OBJECTS_DIR = $${PWD}
TARGET = some_target
TEMPLATE = some_qmake_template
common.pri: configurations common to both projects.

Concerning your fears that CMake might be too complicated: I have been working on projects using both build systems. While I agree that qmake is probably easier to begin with, CMake definitely has its merits, too:
It makes out-of-source builds very easy. Just execute cmake <Path to source> in your build directory. This is great when your sources are on an NFS share, for example, and you want the object files to be placed on a local file system.
Its support for finding additional libraries is very powerful. Lots of FindXXX.cmake files are already shipped with your CMake distribution, making the inclusion of "heavy" libraries such as OpenCV as easy as FIND_PACKAGE(OpenCV REQUIRED).
It even has out-of-the-box support for Qt. In fact, I use it for a larger software project where Qt is used for the GUI part. We decided on CMake because we required platform independence and multiple libraries which we could not easily add via qmake.
All in all, use the build system you are comfortable with (as long as your build system does not inhibit your software development).

Related

What is the best way of CMake in a Middle-sized Project?

In my company, we're developing a middle sized project which we plan to use CMake as the build platform generator. In this scenario, me and my colleagues were discussing about which way the CMake should be used. Our discussions came to a turn which we must decide the methods to use. Our directory structure is similar to this:
<"our project"> \
modules \
module_1 \
tests \
test_example.cpp
mock
some_mock_class.hpp
some_class.hpp
some_class.cpp
...
module_2 \
...
module_3 \
...
utility \
...
1- First thing is first, my colleague thinks that folders like "src" and "includes" are reminder of C programming and has no place in a modern C++ program, so we don't need them. So we removed them from the structure, but being a Linux guy; I'm not sure if this is a good idea. Should we set a "include" directory for headers, so CMake can install them appropriately to the include dirs of the install target; or can CMake handle them appropriately?
2- Should we make a CMakeLists.txt to the root of the project which includes and defines all the targets, or should we make a CMakeLists.txt per module, and then use "add_subdirectory" directives to include them? My colleague thinks on CMakeLists.txt is the best, because this way the module implementors don't need to think about CMake at all, and one or two admins of deployment can maintain the file; but I think every module implementor is more aware of which libraries they use, and how to compile their modules - which he disagrees. What do you suggest in this case?
If you did use CMake for such a middle-sized project before (or know of a case) can you please recommend us what they did and, if possible, why?
Sincerely
The topic is huge, but in short my personal recommendation. For a middle project I assime a component model should be already applied. Then reasonable then is, to have component directories with their onwn CMakeLists.txt which are referenced by the top-level CMakeLists.txt via add_subdirectory(). Each component - a separate library (I like static ones).
For the component folders I find reasonable to hide all internal stuff (aka implementation and private headers, ...) under a private sub-directory to do not be exposed to the outside. Then, in the top component directory you have only headers which are to be used by the others. In the private directory you can mix sources and headers - this is only a matter of the taste for mid projects. And the private directory can also be decomposed if the component is large. But then you need to decide either to add all artifacts to the single CMakeLists.txt of the component, or to have sub-libraries. But in that case the users should link to them individually instead to link to the component's library only.
In the best case, the folder structure should follow the dependencies structure and form a tree-view build system, where the components have as less knowlege about internals of the other components as possible. In that case you will have a good configurability and flexibility in case of possible refactorings. In the other words, the design of the build system seems to me similar to the class design in C++ - same principles.
The real (target) build directory where you run cmake can be located anywhere, normally outside of the source directory. A good place for it could be a RAM disc if you enough memory. Then for the clean build you need just to remove it, that's it. But the source and the build itself have no dependency from its location.
Ah yes, one more hint. My recommendation would be to include headers by the path starting from the component directory like #include "SomeHeader.hpp" which is located as ComponentX/SomeHeader.hpp. Then the CMakelists.txt is used to do the ComponentX directory known to your component. This means, the paths to the headers are not hardcoded in the source files. This brings some limitation like unique file names, but makes changes to the components location much easier.
Hope this anyhow helps.

Autotools: Including a prebuilt 3rd party library

I'm currently working to upgrade a set of c++ binaries that each use their own set of Makefiles to something more modern based off of Autotools. However I can't figure out how to include a third party library (eg. the Oracle Instant Client) into the build/packaging process.
Is this something really simple that I've missed?
Edit to add more detail
My current build environment looks like the following:
/src
/lib
/libfoo
... source and header files
Makefile
/oci #Oracle Instant Client
... header and shared libraries
Makefile
/bin
/bar
... source and header files
Makefile
Makefile
/build
/bin
/lib
build.sh
Today the top level build.sh does the following steps:
Runs each lib's Makefile and copies the output to /build/lib
Runs each binary's Makefile and copied the output to /build/bin
Each Makefile has a set of hardcoded paths to the various sibling directories. Needless to say this has become a nightmare to maintain. I have started testing out autotools but where I am stuck is figuring out the equivalent to copying /src/lib/oci/*.so to /build/lib for compile time linking and bundling into a distribution.
I figured out how to make this happen.
First I switched to a non recursive make.
Next I made the following changes to configure.am as per this page http://www.openismus.com/documents/linux/using_libraries/using_libraries
AC_ARG_WITH([oci-include-path],
[AS_HELP_STRING([--with-oci-include-path],
[location of the oci headers, defaults to lib/oci])],
[OCI_CFLAGS="-$withval"],
[OCI_CFLAGS="-Ilib/oci"])
AC_SUBST([OCI_CFLAGS])
AC_ARG_WITH([oci-lib-path],
[AS_HELP_STRING([--with-oci-lib-path],
[location of the oci libraries, defaults to lib/oci])],
[OCI_LIBS="-L$withval -lclntsh -lnnz11"],
[OCI_LIBS='-L./lib/oci -lclntsh -lnnz11'])
AC_SUBST([OCI_LIBS])
In the Makefile.am you then use the following lines (assuming a binary named foo)
foo_CPPFLAGS = $(OCI_CFLAGS)
foo_LDADD = libnavycommon.la $(OCI_LIBS)
ocidir = $(libdir)
oci_DATA = lib/oci/libclntsh.so.11.1 \
lib/oci/libnnz11.so \
lib/oci/libocci.so.11.1 \
lib/oci/libociicus.so \
lib/oci/libocijdbc11.so
The autotools are not a package management system, and attempting to put that type of functionality in is a bad idea. Rather than incorporating the third party library into your distribution, you should simply have the configure script check for its existence and abort if the required library is not available. The onus is on the user to satisfy the dependency. You can then release a binary package that will allow the user to use the package management system to simplify dependency resolution.

The right way to structure my c++ project with cmake?

I have been struggling with this for quite a while, and my adventures with cmake have only resulted in hackish solutions that I am pretty sure are not correct.
I created a library that consists of several files, as follows:
-libfolder
-codepart1folder
-CMakeLists.txt
-codepart1.cpp
-codepart1.hpp
-codepart2folder
-codepart3folder
-lib.cpp
-lib.hpp
-CMakeLists.txt
I wrote a CMakeLists file to compile the library (after some experimentation), and I can generate a lib.a file. Now I would like to include this code as a library in other projects, and access it through the interface in lib.hpp. What is the best way to do this, in terms of directory structure, and what I need to put into CMakeLists.txt in my root project?
My current attempt has been to add -libfolder as a subfolder to my current project, and add the commands:
include_directories(${PROJECT_SOURCE_DIR}/libfolder)
link_directories(${PROJECT_BINARY_DIR}/libfolder)
add_subdirectory(libfolder)
target_link_libraries(project lib)
When I run make, the library compiles fine, but when project.cpp compiles, it complains that it cannot find codepart1.hpp (which is included in lib.hpp, included from project.cpp).
I suspect that this is the wrong way about doing this, but I cannot wade through the CMake documentation and find a good tutorial on setting up projects like this. Please help, CMake gurus!
The clean way to import one CMake project into another is via the find_package command. The package declaration is done by using the export command. An advantage of using find_package is that it eliminates the need to hard-code paths to the package's files.
Regarding the missing hpp file, you didn't include codepart1folder, so it's not on the include path.
Ok, so after consulting a coworker of mine who is a CMake guru, it seems CMake does not have support for what I am trying to do, leaving one with 3 options:
Add all of the dependencies to the parent projects CMakeLists.txt - not very clean, but it will get the thing to work. You'll have to do this for every project you add the code to, and go back and fix things if your library changes.
clean up your library headers. This is done through some compiler hackery. The idea is to forward-declare every class, and use only pointers or boost::shared_ptr, and then include the dependencies only in the cpp file. That way you can build the cpp file using all the findpackage stuff, and you get the bonus of being able to use the lib by only including the header and linking to the library.
Look into build systems. Having portable code and fast code compilation with complex dependencies is not a solved problem! From my investigations it turned out to be quite complicated. I ended up adopting my coworkers build system which he created himself in cmake, using things he picked up from Google.
Looking at your post you don't seem to add 'codepart1folder' to the includes anywhere. How are you including codepart1.hpp as:
#include <codepart1.hpp>
#include "codepart1folder/codepart1.hpp"
I don't think there is a standard accepted way to structure cmake projects. I've looked at a bunch of cmake repos and they tend to have differences. Personally I do the following:
-project
CMakeLists.txt
-build
-cmake
OptionalCmakeModule.cmake
-src
-Main
Main.cpp
Main.hpp
-DataStructs
SomeTree.hpp
SomeObject.hpp
-Debug
Debug.hpp
-UI
Window.hpp
Window.cpp
Basically that dumps all the source code into 1 directory, then you perform an out of source build with: 'mkdir build && cd build && cmake .. && make' in the projects root folder.
If you have separate libs as part of your project, then you might want a separate libs directory with another subfolder for your specific lib.
I have some of my repos on: https://github.com/dcbishop/ if you want to look at the CMakeLists.txt files.
The main problems with my project structure are that I use the FILE_GLOB which is apparently the 'wrong' way to do things (if you add files after running 'cmake ..' then they won't be picked up hen you do a 'make'). I haven't figured out what the 'right' way to do it is (from what I can see it involves keeping a separate list of files) I also only use 1 CMakeLists.txt file.
Some projects also choose to separate their cpp and hpp files into separate directories. So you would have an include and src folders (at least for the hpp files that are intended to be used externally). I think that would mainly be for projects that are mainly large libraries. Would also make installing header files much easier.
You are probably missing
include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder)
In such a case you might want to set( CMAKE_INCLUDE_CURRENT_DIR on) to add all folders to the include directory path variable.
Check cmake's output on the command line whether the correct include folders are set or not. Additionally you can always use message() as "print debugging" for cmake variables.
In case of include directories however you need to read the directory property to see what is actually in the include directories.
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")
I hope this helps you figuring out what is missing.
Edit
I just saw your comment about added codepart1folder in the libfolder. It is only available in the libfolder's include_directory path and not propagated to the root folder.
Since the include codepart1.hpp is present in the lib.hpp however you need to have it also available in the project path otherwise you will get missing declaration errors when you build your project.

Should I separate CMakeList.txt from source folder?

I'm new to build tool, when I come across Autotool, I have an option to write only one Makefile.am in the top build folder and leave the source folder containing all cpp files clean. I could use VPATH to tell automake to look for the source code inside that folder instead of write /src/ every where. (refer to my old question here: Automake Variables to tidy up Makefile.am)
However It appears to me that CMake have no VPATH to set and some fox around said that It's impossible to do so. So there are two choices:
Create CMakeList.txt in the source folder
Create CMakeList.txt in top build folder and leave the source alone, with a cost that I need to extend "/src" to every source code files.
Which one is more commonly use? I prefer the second because It leave my source code clean from any build-relating-source. In that case is there anyway to get rid of "/src"?
In our company we're using the first option, having a CMakeLists.txt in every subdirectory and building the tree from a root-CMakeLists.txt by using the add_subdirectory command.
This is a modular approach where each subcomponent (think about the project has different parts like boost is split up into system, thread, date_time etc) has its own build-file. If a user wants he is able to just build the subcomponent or to build the whole project.
We're additionally using this as an easy way to include optional subcomponents to the project. The user then can set a Bool value like BUILD_SUBFOO and the add_subdirectory will just be executed, if this Bool is TRUE.
Well-known projects are using this approach too. Here is a link to the root CMakeLists.txt from KDevelop (look at lines 52-62).
I'm quite sure you can do:
FILE(GLOB Source_files src/*.cpp)
which would do exactly what you want.

organizing external libraries and include files

Over the years my projects use more and more external libraries, and the way I did it starts feeling more and more awkward (although, that has to be said, it does work flawlessly). I use VS on Windows, CMake on others, and CodeComposer for targetting Digital Signal Processors (DSPs) on Windows. Except for the DSPs, both 32bit and 64bit platforms are used.
Here's a sample of what I am doing now; note that as shown, the different external libraries themselves are not always organized in the same way. Some have different lib/include/src folders, others have a single src folder. Some came ready-to-use with static and/or shared libraries, others were built
/path/to/projects
/projectA
/projectB
/path/to/apis
/apiA
/src
/include
/lib
/apiB
/include
/i386/lib
/amd64/lib
/path/to/otherapis
/apiC
/src
/path/to/sharedlibs
/apiA_x86.lib -->some libs were built in all possible configurations
/apiA_x86d.lib
/apiA_x64.lib
/apiA_x64d.lib
/apiA_static_x86.lib
/apiB.lib -->other libs have just one import library
/path/to/dlls -->most of this directory also gets distributed to clients
/apiA_x86.dll and it's in the PATH
/apiB.dll
Each time I add an external libary, I roughly use this process:
build it, if needed, for different configurations (release/debug/platform)
copy it's static and/or import libraries to 'sharedlibs'
copy it's shared libraries to 'dlls'
add an environment variable, eg 'API_A_DIR' that points to the root for ApiA, like '/path/to/apis/apiA'
create a VS property sheet and a CMake file to state include path and eventually the library name, like include = '$(API_A_DIR)/Include' and lib = apiA.lib
add the propertysheet/cmake file to the project needing the library
It's especially step 4 and 5 that are bothering me. I am pretty sure I am not the only one facing this problem, and would like see how others deal with this.
I was thinking to get rid of the environment variables per library, and use just one 'API_INCLUDE_DIR' and populating it with the include files in an organized way:
/path/to/api/include
/apiA
/apiB
/apiC
This way I do not need the include path in the propertysheets nor the environment variables. For libs that are only used on windows I even don't need a propertysheet at all as I can use #pragmas to instruct the linker what library to link to.
Also in the code it will be more clear what gets included, and no need for wrappers to include files having the same name but are from different libraries:
#include <apiA/header.h>
#include <apiB/header.h>
#include <apiC_version1/header.h>
The withdrawal is off course that I have to copy include files, and possibly** introduce duplicates on the filesystem, but that looks like a minor price to pay, doesn't it?
** actually once libraries are built, the only thing I need from them is the include files and thie libs. Since each of those would have a dedicated directory, the original source tree is not needed anymore so can be deleted..
Why not use file system links?
ln -s /path/to/apis/apiA/include /path/to/api/include/apiA
Voilá. Similar can be done on Windows, but I don't have the command line handy right now.