I'm using qmake for building a project of mine. I have been trying to set the DESTIR variable of qmake with a value that depend of the compiler used. Actually, I want that the binary of my project, after builded, be placed in a directory that has the name of the compiler used to build it.
Something like this... My current directory tree for my project is
- Project
| - src
| - include
| - bin
| |- binary_file
I wanted it to be like this
- Project
| - src
| - include
| - bin
| | - gcc-4.3.4
| | |- binary_file
Can I do this using qmake?
In the src/src.pro file, or wherever you set the DESTDIR
# compiler used
QMAKE_CXX = g++-4.3
# PROJECT_ROOT defined in .qmake.cache as $$PWD, in the Project root directory
DESTDIR = $$PROJECT_ROOT/bin/$$QMAKE_CXX/
If you don't want to set the compiler version, you can query it dynamically. I don't know if there is any general c++/qmake solution for it, but with g++ you can use -dumpversion:
CXX_VERSION = $$system($$QMAKE_CXX -dumpversion)
DESTDIR=$$PROJECT_ROOT/bin/$$QMAKE_CXX-$$CXX_VERSION/
Related
I have a project that I'm trying to configure to make use of CMake, and to make my life easier I'm organizing it as a series of libraries that I'm treating as subprojects.
MyProject
|-- common-cmake
| |-- common-functions1.cmake
| |-- common-functions2.cmake
| `-- CMakeLists.txt
|-- lib1
| |-- include
| | `-- someClass.h
| |-- src
| | `-- someClass.cpp
| |-- test
| | |-- include
| | | `-- someClassTest.h
| | |-- src
| | | `-- someClassTest.cpp
| | `-- CMakeLists.txt
| `-- CMakeLists.txt
|-- lib2
| `-- <snip>
|-- lib3
| `-- <snip>
`-- CMakeLists.txt
There's a global CMakeLists.txt in MyProject that handles the cross-library specifics (such as version information and installation directories) and ensures that everything is included via
add_subdirectory(cmake-common)
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(lib3)
common-cmake contains common logic to avoid repetition in each library's or test's CMakeLists.txt (such as common shared library definition since all of the libraries have a common structure). Each library contains a CMakeLists.txt with the necessary information so that it itself can be compiled, and includes its test directory. Each test in turn has its own CMakeLists.txt to provide the necessary details for the compilation of the tests for the library it is contained within. Thus, both the library and its test CMakeLists.txt is dependent on details the global CMakeLists.txt provides and functions that are contained within the common-cmake.
After fighting with the specifics of this, I've got it working. I can kick-off a build from the global level and build/test/install all libraries as well as for an individual library via the appropriate make target.
Now that I've got this working at the global level, I'm trying to get this working in Eclipse. I've managed to get the global project imported and working by calling
cmake -G "Eclipse CDT4 - Unix Makefiles"
at the global level, however this means that everything is contained within a single Eclipse project and I find it extremely unwieldy to work with. Ideally I'd like to have each of the libraries as its own project within Eclipse. I can import the library as a project from within Eclipse directly, but when I do that Eclipse in turn starts throwing errors relating to failure to CMakeCache.txt not existing, or the common functions from common-cmake not being available (since it's not longer starting from the global CMakeLists.txt, those common files are never added).
The only way around this that I can think of would be to allow each library to be both part of the global project (as it is right now) as well as to be usable independently. I've been trying to figure out how this could be done, but unfortunately I haven't had any success.
add_subdirectory("..")
add_subdirectory("../common-cmake")
add_subdirectory doesn't allow me to add anything that's outside of the current directory's subdirectories (which makes a lot of sense), and the only way I've found is to include each file individually and have a rather ugly flag in place to prevent duplication, where the global and the project check each other's flag to prevent stepping on each other's toes.
# Global CMakeLists.txt
add_subdirectory(cmake-common)
if(NOT DEFINED ${PROJECT_BUILD})
set(FULL_BUILD true)
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(lib3)
endif()
# lib CMakeLists.txt
if(NOT DEFINED ${FULL_BUILD})
set(PROJECT_BUILD true)
include("../common-cmake/common-functions1.cmake")
include("../common-cmake/common-functions2.cmake")
endif()
Is there a way to accomplish this? Is what I'm trying to do antithetical to CMake and thus not possible? Is there a better way to achieve my end goal?
For a fairly complex Visual Studio 2013 solution consisting of many large C++ projects, how can I get the paths to all my source code files that end up in my executable for a specific target platform / architecture? This should include the source code from all my projects the application transitively depends on. Example:
Solution
|
+-- Project: Application (depends on "Library A")
| |
| + File: defs.h
| |
| + File: main.cpp
|
+-- Project: Library A (depends on "Library B")
| |
| + File: libA.h
| |
| + File: libA.cpp
|
+-- Project: Library B
|
+ File: libB.h
|
+ File: libB.cpp
In the above, suppose Application depends on Library A, and Library A depends on Library B. When inspecting the Application project, what I'm looking for is the list of paths to the files defs.h, main.cpp, libA.h, libA.cpp, libB.h, libB.cpp.
I'm looking to rely as much as possible on information that is provided by the build tools, like the exact command line that gets passed to the compiler, or some dependency graph. I do not want to write a script that tries to extract all that information from scratch.
Currently, I'm not interested in dependencies to binary / pre-compiled libraries, but only in the source code files that end up in one way or the other in the final executable.
I'm trying to find a way to build a big modular C++ project with CMake.
The structure of the project is the following:
--project_root
--src
--folder_1
--source_1.h
--source_1.cc
--test_source_1.cc // file containing a main with unit tests
--folder_2
--source_2.h
--source_2.cc
--test_source_2.cc // file containing a main with unit tests
--folder_3
...
And so on.
Each folder represent a project module and each module might depend on other modules, so for example source_1.h may include source_2.h.
Every module folder may also contains a test file so the whole project will have multiple executables.
How can I build the whole project with CMake? How should I write my CMakeLists.txt file?
Thank you a lot.
There are many, many examples out there of how to structure CMake projects for C++, many of which are referenced by the tutorial #user2485710 suggested in his comment, so I'm not going to go super in-depth here, but I'll at least give you a good starting point based on the way you want to lay out you folder structure.
The nice thing about CMake is that it can essentially do a tree-decent using the add_subdirectory command. This lets us easily divide up our CMake code to only do what is required at any specific directory level. In otherwords, each CMakeLists.txt file should only do the minimal amount of work needed to properly set up things at the current depth in the directory tree. In you example, your CMake tree might look like this:
--project_root
--src
--CMakeLists.txt
--folder_1
--CMakeLists.txt
--source_1.h
--source_1.cc
--test_source_1.cc // file containing a main with unit tests
--folder_2
--CMakeLists.txt
--source_2.h
--source_2.cc
--test_source_2.cc // file containing a main with unit tests
...
In src/CMakeLists.txt you do all of your project-level initialization, I.E. find_package, setting up your include-path, etc. Then you simply add the following at the end:
add_subdirectory(folder_1)
add_subdirectory(folder_2)
...
This tells CMake that it should look in those folders for additional stuff to do. Now in src/folder_1/CMakeLists.txt, we do the actual work of whatever combination of add_executable and add_library you need to properly build source_1.cc and test_source_1.cc, and likewise in src/folder_2/CMakeLists.txt for source_2.cc, etc.
The other nice thing is that any CMake variables you set higher up the tree are propagated down through add_subdirectory. So, for example, in src/CMakeLists.txt you can check for some sort of 'build unit-test' flag and set the CMake variable there, and then all you have to do in the other CMakeLists.txt files is check for that variable. This can also be super useful to do if you have a project where CMake is dynamically generating header files for you based on checking environment variables for path-names and the like.
If the structure of the project is well-regulated, you could write custom macros or function of cmake to define the modules and their dependencies.
The cmake scripts in OpenCV project is a good reference:
/libs/opencv-2.4.8/sources/
|+cmake/
|+doc/
|~modules/
| |+core/
| | |+doc/
| | |+include/
| | |+perf/
| | |+src/
| | |+test/
| | `-CMakeLists.txt
| |~imgproc/
| | |+doc/
| | |+include/
| | |+perf/
| | |+src/
| | |+test/
| | `-CMakeLists.txt
| |+ml/
| |+...
| |-CMakeLists.txt
|-CMakeLists.txt
root/modules/imgproc/CMakeLists.txt
set(the_description "Image Processing")
ocv_define_module(imgproc opencv_core)
You will need a CMakeLists.txt in each folder where building will occur.
project() is used to set the name of your overall project.
add_subdirectory() is used to command the configuration to process the CMakeLists.txt in that directory.
add_executable() is used to create an executable from included sources.
add_library() is used to create a static or dynamic library that can be added to executables or libraries as a dependency.
Using a build script (.bat, .cmd, or .sh) will allow you to automate some of the cmake process, such as setting up an out-of-source configuration or build.
You should look up the documentation for these commands on the cmake website, https://cmake.org/cmake/help/latest/
I started playing around with CMake to create a project with Qt and test it with Google Test. At the moment, I succesfully found a way to compile and link all the required libraries. However, I couldn't find a way to link sources to test files with following project structure:
root
|
+-- CMakeLists.txt
+-- src
| |
| +-- CMakeLists.txt
| +-- MyClass.h
| +-- MyClass.cpp
|
+-- test
| |
| +-- CMakeLists.txt
| +-- MyClassTest.cpp
|
+-- lib
|
+-- gtest-1.6.0
|
+-- CMakeLists.txt
Root CMakeLists.txt contains add_subdirectory for gtest, src and test folders. I have succesfully compiled and run "Hello world" app and simple EXPECT_TRUE(true) test in order to check that each part compiles correctly. Unfortunately, I couldn't find a way to include my source file to tests. Is it possible with the following project structure?
PS I know that it is possible to compile my sources as a library and link it to tests, but I dislike that approach, since it is more appropriate for integration testing, rather then unit testing...
EDIT: Added class names to the tree
You can add a global variable at the level of your root CMakeLists.txt:
set(ALL_SRCS CACHE INTERNAL "mydescription" FORCE)
In the first add_subdirectory(src), you can do:
set(ALL_SRCS ${ALL_SRCS} blabla.cpp CACHE INTERNAL "description")
And in the add_subdirectory(test), you continue with:
set(ALL_SRCS ${ALL_SRCS} bla_test.cpp CACHE INTERNAL "description")
You can then do, add_executable, or library or whatever, with all your sources files.
EDIT: add trick for global variables in CMake.
In the root CMakeLists.txt you can add a include_directories(src) This will then also be used by the tests. Another thing you can do is in the test CMakeLists.txt add a include_directories(${<projectName>_SOURCE_DIR}) where projectName is the name specified using project(myproj) in the src/ CMakeLists.txt (if you specified a project in there of course. Also check the docs about project)
When I move some subdirectory away from project managed by "./configure" and all that things, it tries to get to some "../../configure.ac" and other things and is not easily buildable.
How to extract part of such project and make it independent?
There is two ways to deal with this, create a separate auto-tools build process or do away with the auto-tools and hand code or make a new Makefile.
myprojectfoo
|
+-- src
|
+-- man
|
+-- messages
|
+-- lib
|
+-- include
|
+-- others
Have a look at the illustration above, for a fictitious project called myprojectfoo and is using auto-tools to build a binary called foo. The top-level directory i.e. myprojectfoo will have configure.ac, Makefile.am and Makefile.in, in the subdirectories there would be at least Makefile.am and Makefile.in. The auto-tools will create and execute the make commands to build the project.
Now, from what I'm understanding in what you are trying to do:
myprojectfoo
| \ /
+-- sXc
| / \
+-- man
|
+-- messages
|
+-- lib
| \ /
+-- incXude
| / \
+-- others
You want to take out the src subdirectory and it's include's also. Then in that case, it would be easier to create a separate Makefile (read - no auto-tools) build.. in that case, it would be easier.
The best way I can think of it is, you will have to make that decision ultimately, how big is the subset of the project's sources you want to extract, once you go ahead with that, remove all references to Makefile.am, Makefile.in... and borrow an existing simple Makefile template to build it and invoke it like this
make -f MyMakefile
OR
If you want to build a separate project using that subset using auto-tools:
Create a bare-bones Makefile.am as shown below.
Create a bare-bones configure.ac as shown below...
Run autoscan on the source to pick out the dependencies, add the results of the output file 'configure.scan' to the configure.ac
Run automake (Do this once!)
Run autoconf then. It may complain about missing files such as INSTALL, COPYING etc
Then any subsequent changes to configure.ac, run autoreconf after that, which will execute automake, autoconf, and other supporting auto-tools programs.
Taking a sample of the Makefile.am for Linux...
SUBDIRS = src include
ACLOCAL_AMFLAGS = -I m4
Taking a sample of the configure.ac for Linux...
AC_PREREQ(2.63)
AC_INIT([mysubsetprojectfoo], [0.1a], [foo#bar.baz])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([-Wall -Werror])
AM_GNU_GETTEXT_VERSION([0.17])
AM_GNU_GETTEXT([external])
AM_CFLAGS=
# Checks for programs.
AC_HEADER_STDC
AC_PROG_CC
AC_ARG_ENABLE([debug],
[ --enable-debug Turn on debugging],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
esac],[debug=false])
AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
# Checks for libraries.
AC_CHECK_LIB([mylib], [mylib_function], [:])
if test "$mylib" = :; then
AC_MSG_ERROR([MyLib is missing.\
This can be downloaded from 'http://www.foo.baz'])
fi
AC_CONFIG_HEADERS([config.h])
# Checks for header files.
# FROM running 'autoscan' on the source directory
AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h locale.h netinet/in.h stdlib.h string.h sys/ioctl.h sys/socket.h syslog.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
AC_C_CONST
AC_TYPE_SIGNAL
AC_TYPE_PID_T
AC_TYPE_UID_T
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_CHECK_FUNCS([atexit inet_ntoa memset regcomp socket strdup strerror])
AC_CONFIG_FILES([Makefile src/Makefile include/Makefile])
AC_OUTPUT
The commands for the auto-tools, is top of my head and I may have missed something..feel free to point out by placing a comment on this at the bottom of this post and it will be amended accordingly.