I have an C++ project in Eclipse that uses Autoconf and Automake. My (simplified) project structure is the following:
+-- Makefile.am
+-- configure.ac
+-- src/
| +-- 4Bench.cpp
| | +-- Makefile.am
| | +-- folder1/
| | | +-- ...
| | +-- folder2/
| | | +-- ...
| | +-- folder3/
| | | +-- ...
+-- include/
| +-- ...
The folder src/ will contain multiple binaries (4Bench.cpp is one of them) that will use the .cpp files located in folder1, folder2, etc. All the header files are located in include/. My src/Makefile.am looks as follows:
bin_PROGRAMS=4Bench
4Bench_SOURCES=4Bench.cpp folder1/file11.cpp folder2/file21.cpp ...
4Bench_CPPFLAGS=-I$(top_srcdir)/include
AM_CPPFLAGS=$(BOOST_CPPFLAGS)
AM_LDFLAGS=$(BOOST_LDFLAGS)
4Bench_LDADD=$(BOOST_PROGRAM_OPTIONS_LIB)
Since I expect to have many files in the subfolders of src/, I want to use wildcards to have something like:
4Bench_SOURCES=4Bench.cpp $(wildcard folder1/*.cpp) $(wildcard folder2/*.cpp) $(wildcard folder3/*.cpp)
Unfortunately this leads to a bunch of errors of the form "undefined reference", that is, the compiler cannot find the implementation of the classes in the .cpp files. Enumerating every single file that is required by the binary works. For further reference I provide both the ./configure.ac and ./Makefile.am files.
./configure.ac
AC_PREREQ(2.59)
AC_INIT(4Bench, 0.1)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects -Wno-portability])
AC_PROG_CXX
AC_CONFIG_MACRO_DIR([m4])
AX_CXX_COMPILE_STDCXX_11
AX_BOOST_BASE([1.32],,[AC_MSG_ERROR([4Bench needs Boost, but it was not found in your system])])
AX_BOOST_PROGRAM_OPTIONS
AX_BOOST_UNIT_TEST_FRAMEWORK
AC_CONFIG_FILES(Makefile src/Makefile test/Makefile)
AC_OUTPUT
./Makefile.am
SUBDIRS=src test
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
EXTRA_DIST = bootstrap
Any ideas about how to solve the issue? I am using Linux Mint 18 with g++ 5.4.0, autoconf 2.69 and GNU automake 1.15. Thanks for your attention & help!
Any ideas about how to solve the issue?
You can't do that with the current implementation of automake. This is a feature.
Related
to start with, I have the following repo structure.
root
|
|--- blocks
| |
| |---example
| |
| |---example.cpp
| |---CMakeLists.txt
|
|--- interfaces
|
|--- types
|
|-- types1.h
|-- types2.h
|-- CMakeLists.txt
What I would like to do is to only include types1.h in the cmake target of example.cpp. And I would like to include types1.h such that I can include it in example.cpp using its path relative to root (i.e. #include "interfaces/types/types1.h") and I don't want to use include_directories(${CMAKE_SOURCE_DIR}) since that would expose the whole repo to the target.
target_include_directories did not work since it only includes directories but not individual files and I don't want to include a whole directory and expose irrelevant headers in types folder to example.cpp or move types1.h to a dedicated subfolder.
Do you have any suggestions on how to achieve this?
My current solution is as below which gives fatal error: interfaces/types/types1.h: No such file or directory when I compile exampleblock target. (I eased the requirements for start and allowed interface_types target to include types2.h also even though example.cpp doesn't need it)
blocks/example/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
add_library(exampleblock STATIC
example.cpp
)
target_link_libraries(exampleblock INTERFACE
${CMAKE_SOURCE_DIR}/interfaces/types:interface_types
)
interfaces/types/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
add_library(interface_types INTERFACE)
target_include_directories(interface_types INTERFACE .)
I'm working on a library which will be used by another project. The main project uses a couple of libraries linked as git submodules. Inside the library project used as a submodule, I can set the LIBRARY_OUTPUT_DIRECTORY and the ARCHIVE_OUTPUT_DIRECTORY in two different ways.
In option A the targets are built and saved to their own subdirectories using the ${PROJECT_BINARY_DIR}/lib, but in option B all targets are built and saved to the ${CMAKE_BINARY_DIR}/lib directory.
This could also be extended to binaries built by the submodules. Thus, which of the two options will scale better / is normally used as best-practice?
OPTION A
CMakeLists.txt
# Set target properties
set_target_properties(${PROJECT_NAME}_lib_shared PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set_target_properties(${PROJECT_NAME}_lib_static PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/static)
Folder Structure
.
+-- build
| +-- bin
| +-- MainProject
| +-- test
| +-- lib
| +-- SubModuleA
| +-- SubModuleA_lib_shared.a
| +-- static
| +-- SubModuleA_lib_static.so
| +-- SubModuleB
| +-- SubModuleB_lib_shared.a
| +-- static
| +-- SubModuleB_lib_static.so
+-- lib
| +-- SubModuleA
| | +-- CMakeLists.txt
| +--- SubModuleB
| | +-- CMakeLists.txt
+-- inc
| +-- foo.h
+-- src
| +-- foo.cpp
| +-- main.cpp
| +-- CMakeLists.txt
+-- test
| +-- test.cpp
| +-- CMakeLists.txt
+-- CMakeLists.txt
OPTION B
CMakeLists.txt
# Set target properties
set_target_properties(${PROJECT_NAME}_lib_shared PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(${PROJECT_NAME}_lib_static PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/static)
Folder Structure
.
+-- build
| +-- bin
| +-- MainProject
| +-- test
| +-- lib
| +-- SubModuleA_lib_shared.a
| +-- SubModuleB_lib_shared.a
| +-- static
| +-- SubModuleA_lib_static.so
+-- SubModuleB_lib_static.so
+-- lib
| +-- SubModuleA
| | +-- CMakeLists.txt
| +--- SubModuleB
| | +-- CMakeLists.txt
+-- inc
| +-- foo.h
+-- src
| +-- foo.cpp
| +-- main.cpp
| +-- CMakeLists.txt
+-- test
| +-- test.cpp
| +-- CMakeLists.txt
+-- CMakeLists.txt
Unless there is a good reason you shouldn't set the output directory for your targets in the library project at all. If consumers link to the CMake targets provided by the library project then they usually don't even need to know where exactly these libraries will be located, and even if they do they have access to the location through target-dependent generator-expressions.
Moreover, even if you do have a good reason (e.g. because you'd like to archive the build-artifacts in a CI build and don't use CPack to generate proper packages yet), you still shouldn't force your setup upon consumers. If you allow consumers to easily overwrite the defaults they can e.g. use that mechanism to ensure the shared libraries will be located next to a binary their project builds, which is required on Windows to run the executable without having to manually modify the PATH to include all directories where the dependencies are located, i.e. consumers can ensure that the executable can be run from the build tree by changing the default output directory of your library target.
You thus shouldn't set the target properties, and instead set the defaults for these properties by setting
if (NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib/static")
endif()
if (NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
endif()
if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
endif()
to make it more convenient for consumers to change the output location of all targets all at once without having to set the properties manually for each target again.
Whether you use ${PROJECT_BINARY_DIR} or ${CMAKE_BINARY_DIR} then is largely irrelevant, but I personally prefer to use ${PROJECT_BINARY_DIR} because it ensures there will be no conflicts, even if two subprojects chose the same name for their target (e.g. several targets might define an executable that is just called tests).
I am attempting to write CMakeLists.txt for a platform. The platform has multiple projects which share some libraries and have their own executables. I wish to be able to build each project as a whole, as well as individual executables from within the project.
out-of-source root build works fine:
mkdir root-build && cd root-build && cmake ../root
out-of-source executable build does not work:
mkdir ui-build && cd ui-build && cmake ../root/project1/ui
My current directory structure is as follows:
root/
+-- CMakeListst.txt
+-- lib/
+-- CMakeLists.txt
+-- sharedLib1/
+-- CMakeLists.txt
+-- sharedLIb2/
+-- CMakeLists.txt
+-- project1/
+-- CMakeLists.txt
+-- ui/
+-- CMakeLists.txt
+-- executable1/
+-- CMakeLists.txt
+-- shared/
+-- CMakeLists.txt
+-- project2/
+-- CMakeLists.txt
+-- executable/
+-- CMakeLists.txt
My current project structure builds all targets and libraries as part of the project great, but I can't figure out how to build an executable in isolation.
The main cmake file for a project is root/project*/CMakeLists.txt. This file INCLUDES root/CMakeLists.txt, which does some setup common to all projects (e.g setting CMAKE_MODULE_PATH and find_package for third-party libraries). The project cmake file also calls add_subdirectory for each of it's executables and add_subdirectory(../lib libs).
This allows executables to link against any of the targets defined in the root/lib subdirectory. If I then try to build the executable independently of the project, CMake will not be able to find the target the executable needs to link against. Is there an elegant solution / pattern that would allow this? One way I thought of was to just add_subdirectory(../../ root) from the ui/CMakeLists.txt, with something resembling header guards to prevent an infinite add_subdirectory loop.
Use make executable1 (for example) to build individual targets.
First time user here so pleasy be gentle.
I have problem with linking libraries using cmake.
I'am working on part of the bigger project. Each part has its own build system, but can use libraries from other parts. Eample project tree:
+-- Project
| +-- Part1
| +-- Lib1
| +-- libLib1.a
| +-- Lib2
| +-- libLib2.a
| +-- Part2
| +-- Lib3
| +-- libLib3.a
| +-- Lib4
| +-- libLib4.a
| +-- MyPart
| +-- Lib5
| +-- libLib5.a
| +-- Lib1.cpp
| +-- CMakeLists.txt
| +-- main.cpp
| +-- CMakeLists.txt
I try to link my part MyPart, with libraries Lib1, Lib2, Lib4, Lib5.
With Lib5 there is no problem as it is build with the same cmake tree.
But how to link outside libraries?
I choose to use find_library to obtain path to each of the other needed library, for example:
find_library(LIB1_LIBRARY
NAMES Lib1
PATH ../Part1/Lib1/)
And then use target_link_libraries. Unfortunetly as a result of find_library i get LIB1_LIBRARY-NOTFOUND.
But if keyword NAMES is to be removed, all start working as expected.
What is wrong here? And also is there better strategy for linking libraries from outside of my build system tree.
thank you in advance
I read this brilliant tutorial about how to integrate Google Test with CMake. The outline of the project there looks like this:
+-- CMakeLists.txt
+-- main
| +-- CMakeLists
| +-- main.cpp
|
+-- test
| +-- CMakeLists.txt
| +-- testfoo
| +-- CMakeLists.txt
| +-- main.cpp
| +-- testfoo.h
| +-- testfoo.cpp
| +-- mockbar.h
|
+-- libfoo
| +-- CMakeLists.txt
| +-- foo.h
| +-- foo.cpp
|
+-- libbar
+-- CMakeLists.txt
+-- bar.h
+-- bar.cpp
(For the interested, the entire code of this example project can be checked out from here)
The top-level CMakeLists.txt contains (among others) the statements enable_testing() and add_subdirectory(test). Compiling and running test cases works perfectly with this setup, simply by running
mkdir build && cd build
cmake ..
make
make test
But how would I compile this project into production code, i.e. only the components test, libfoo and libbar, without all the unit tests?
Should I make the statements enable_testing() and add_subdirectory(test) somehow dependent on some build configuration variables? Or what's the best practice for this?
To build the tests only on request, I do it in this way:
Add an option option(BUILD_TEST "Build the unit tests" ON)
Include the test subdirs only in case BUILD_TEST is on
if(BUILD_TEST)
add_subdirectory(test)
endif()
In your case you can modify this to testfoo.
As you asked for production, you can use the following instead to build in debug mode only:
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_subdirectory(test)
endif()
What I do is to make a custom macro for unit test creation which does this:
set_target_properties(${NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test)
Then your tests will end up in a special directory (test) instead of the regular one (usually bin). Then for production you just copy the regular directory without the test directory.