I want to get two executables from my C++ source code (test and release). I have two main() functions in two separate C++ files.
With the Meson build system it is easy:
project('PrjName', 'cpp')
mainSrc = ['header1.hpp', 'source1.cpp', 'source2.cpp']
testSrc = ['header2.hpp', 'source2.cpp', 'test.cpp']
mainExe = executable('prjName', mainSrc)
testExe = executable('prjNameTest', testSrc)
I could not get the same with CMake:
cmake_minimum_required(VERSION 3.10)
project("PrjName")
set(SOURCES
"header1.hpp"
"source1.cpp"
"source2.cpp"
)
set(TEST_SOURCES
"header2.hpp"
"source2.cpp"
"test.cpp"
)
add_executable("prjName" ${SOURCES})
add_executable("prjNameTest" ${TEST_SOURCES})
I get the first executable (prjName), but not the second, with the error:
Multiple definition of 'main'
However, the main() functions are defined in "source1.cpp" and "test.cpp", so there should be no conflict.
How can I fix this issue, considering that as it seems from the Meson build the code should be fine?
Building the same code on a different PC, I had no such issue.
I would close/delete this question.
Related
I am new to googletest and CMake. I wanted to learn googletest so I decided to try writing and running some tests on a collection of files I wrote a while back.
My directory looks like:
-CMakeLists.txt
-normTest1.cpp
-deathTest1.cpp
-normTest2.cpp
-deathTest2.cpp
-build
-[all CMake files like Makefile, cache, bin, lib, etc.]
-my_library_dir
-obj1.h
-obj2.h
-obj1.cpp
-obj2.cpp
-my_library.h
Now my CMakeList.txt is: (based on this tutorial: https://google.github.io/googletest/quickstart-cmake.html)
cmake_minimum_required(VERSION 3.14)
project(my-library-testing)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
set(${PROJECT_NAME}_CXX_FLAGS "${${PROJECT_NAME}_CXX_FLAGS} -std=c++17")
set(${PROJECT_NAME}_CMAKE_CXX_FLAGS "${${PROJECT_NAME}_CMAKE_CXX_FLAGS} -std=c++17")
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/e2239ee6043f73722e7aa812a459f54a28552929.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
enable_testing()
add_executable(
library_test
normTest1.cpp
normTest2.cpp
deathTest1.cpp
deathTest2.cpp
)
target_link_libraries(
library_test
gtest_main
)
include(GoogleTest)
gtest_discover_tests(library_test)
and each of my .*Test[12].cpp files have an #include <gtest/gtest.h> and a #include "my_library_dir/my_library.h" in them.
Unfortunately, executing cmake -S . -B build and then cmake --build build gives me a bunch of linker errors because of multiple definitions of functions in the source files of my_libary_dir across each *.o file. How can I edit my CMakeLists.txt file to get around these linker errors? Temporarily, I am only putting one source file in the add_executable(...) and instead #includeing the other source files in the one source file that I include in add_executable.
I'm working on a Websockets library for C++. My project has the library folder and a tests folder.
The tests folder contains many source files that each is compiled as a stand-alone executable and considered a test. The relevant CMakeLists for it looks like this:
file(GLOB TEST_SOURCES "src/*.cpp")
foreach(file ${TEST_SOURCES})
get_filename_component(_F_NAME ${file} NAME_WE)
add_executable(${_F_NAME} ${file})
target_link_libraries (${_F_NAME} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${_F_NAME} tiny_websockets_lib Catch)
if(WIN32)
target_link_libraries(${_F_NAME} wsock32 ws2_32)
endif()
add_test(NAME ${_F_NAME} COMMAND ${_F_NAME})
endforeach()
Basically for every cpp file in src/ I create a new executable and link to it my library (here called tiny_websockets_lib).
The libraries' CMakeLists.txt looks like this:
file(GLOB_RECURSE tinyws_SOURCES
"src/*.cpp"
)
file(GLOB_RECURSE tinyws_HEADERS
"include/*.h"
"include/*.hpp"
)
include_directories(include/tiny_websockets)
add_library(tiny_websockets_lib STATIC ${tinyws_HEADERS} ${tinyws_SOURCES})
set_target_properties(tiny_websockets_lib PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(tiny_websockets_lib PUBLIC include)
The Issue:
In the library I have some conditional compilation flags. For example, this flag:
#define _WS_CONFIG_NO_TRUE_RANDOMNESS
can be defined and it will change the behivour of the library.
The problem is that the library only compiles once, so if my test looks like this:
#define _WS_CONFIG_NO_TRUE_RANDOMNESS
#include <library_stuff_with_conditional_compile_ifdefs>
int main() {
// tests
}
The library will not be compiled again, and the flag will not be considered.
TLDR: To my understanding the library is compiled once and linked multiple times. I would like the library to recompile and consider the main file for every tests.
You can see the actual project and structure here: https://github.com/gilmaimon/TinyWebsockets
Thank You.
I'm not sure whether the title is correct, but anyway:
I'm writing the project with boost and eigen3 libraries, further I would like to test CMake. So far I've written everything in one .cpp file, the header is like:
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <iostream>
#include "eigen/Eigen/Dense"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Hello
#include <boost/test/unit_test.hpp>
#include <cmath>
#include <boost/timer/timer.hpp>
#include <fstream>
Further I added some boost unit tests in my "main" function in the following way
BOOST_AUTO_TEST_CASE(universeInOrder)
{
Eigen::Matrix3d m;
m << 0, 1, 2,
3, 4, 5,
6, 7, 8;
BOOST_CHECK(Min(m) == 1);
}
where Min is a separate function returning the lowest coeff. of matrix.
In my directory I have both FindEigen3.CMake and FindBoost.CMake files. I also have CMakeLists.txt file with the code:
cmake_minimum_required (VERSION 3.0)
project (hello)
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
add_executable (hello hello.cpp)
target_link_libraries (hello Eigen3::Eigen)
enable_testing()
I'm running
mkdir build
cd build
cmake ..
and there are no errors, everything is ok.
To run the program I use
g++ -I /home/fdhd/Documents/boost/ file-name.cpp -lboost_unit_test_framework -lboost_timer -o file-name
And here is my question - can I avoid linking boost in that command above and plug in into CMakeLists.txt file and run just
g++ file-name.cpp ,
so that it will work because everything is in CMakeLists file?
Any ideas? I think that the solution must be just behind the corner, but I can't really see it.
Thanks!
To run the program I use
Nop, that's not the cmake idiomatic way to run/test your program. Since you have enable_testing(), cmake already has a custom target for you to run your binary. According to the CTest wiki, all you need is to type make test after adding add_test function in you CMakeLists.txt. More or less like this:
cmake_minimum_required (VERSION 3.0)
project (hello)
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
add_executable (hello hello.cpp)
target_link_libraries (hello Eigen3::Eigen)
enable_testing()
add_test(test hello)
I am trying to find the best way to link my project source code with my boost unit tests. I have a fairly basic project setup right now using CMake, however all examples of boost UTF that I have come across have shown very basic tests which do not touch source code in a project that is along side the tests.
As a minimal example I have the following:
CMakeLists.txt
cmake_minimum_required(version 2.8)
project(test-project)
find_package(Boost 1.55 REQUIRED COMPONENTS unit_test_framework )
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
add_subdirectory(src)
enable_testing()
add_subdirectory(test)
src/CMakeLists.txt
add_executable(example main.cpp foo.cpp)
src/foo.h
#include <string>
std::string hello(std::string name);
src/foo.cpp
#include "foo.h"
std::string hello(std::string name) { return "Hello " + name; }
src/main.cpp - Uses foo in a simple way
test/CMakeLists.txt
include_directories (../src)
set(TEST_REQUIRED_SOURCES ../src/foo.cpp)
add_executable (test test.cpp ${TEST_REQUIRED_SOURCES})
target_link_libraries(test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_test(SimpleTest test)
test/test.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE SimpleTest
#include <boost/test/unit_test.hpp>
#include "foo.h"
BOOST_AUTO_TEST_CASE(ShouldPass) {
BOOST_CHECK_EQUAL(hello("fred"), "Hello fred")
}
While this works, I'd like to avoid the following:
Defining TEST_REQUIRED_SOURCES with a list of all of my files required to compile.
Avoiding the duplicate compilation of code.
Does my structure look correct for this sort of project? Would it make sense to compile my code under src into a library instead? Most of my experience with testing is from C# where this is much simpler.
You can have a look at how I did it there: https://github.com/NewbiZ/mengine/blob/master/CMakeLists.txt
Basically, I build an object file with my library, and reuse it in the main executable AND the tests. That way you only build once.
The interesting piece of CMake is:
# Just build the object files, so that we could reuse them
# apart from the main executable (e.g. in test)
ADD_LIBRARY(mengine_objects OBJECT ${MENGINE_SOURCES})
Then build the main executable:
ADD_EXECUTABLE(mengine $<TARGET_OBJECTS:mengine_objects>
src/main.cpp)
And the tests:
ADD_EXECUTABLE(test_tga $<TARGET_OBJECTS:mengine_objects>
test_tga.cpp)
Hope that helps!
I have simple project that mixes C and C++ (wrapping a C lib into a C++ class and making it easy to use in C++ project). The project was build with VisualStudio and I'm under Linux or Mac so I'd like to convert it in a CMake project.
The VS project content is full of
<ClInclude Include="a_file.h" />
so I think the file are just included without any complex build system. Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
# project
set(PROJECTNAME "Test")
project(${PROJECTNAME} C CXX)
set (CMAKE_CXX_FLAG "-Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "./")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
find_package(OpenCV REQUIRED)
file(GLOB_RECURSE ${PROJECTNAME}_HEADERS ${CMAKE_SOURCE_DIR}/*.h)
file(GLOB_RECURSE ${PROJECTNAME}_SOURCES ${CMAKE_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE ${PROJECTNAME}_SOURCES ${CMAKE_SOURCE_DIR}/*.c)
include_directories (include)
include_directories (src)
SET(${PROJECTNAME}_SOURCES
main.cpp
${${PROJECTNAME}_SOURCES}
)
ADD_EXECUTABLE(${PROJECTNAME}
${${PROJECTNAME}_SOURCES}
${${PROJECTNAME}_HEADERS}
)
I know that is not a good rule to follow, but I just need a quick and dirty way to use this code.
Now, if I make with this test main.cpp:
#include <iostream>
int main(int argc, char *argv[]) {
std::cout << "main > ." << std::endl;
return 0;
}
I get a duplicate symbol error for CMakeCCompilerId.c
duplicate symbol _main in:
CMakeFiles/Test.dir/main.cpp.o
CMakeFiles/Test.dir/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As far as I get this CMakeCCompilerId.c file is something that cmake add for dealing with C...
So, here my question: what is the cmake-auto-added CMakeCCompilerId.c ? How can I compile a project with a main function that contains bot C and C++?
EDIT:
I resolved the problem just using
project(${PROJECTNAME} CXX)
instead of
project(${PROJECTNAME} C CXX)
But I'm curious anyway to understand it and how CMake mixes the two languages
The file(GLOB_RECURSE ${PROJECTNAME}_SOURCES ${CMAKE_SOURCE_DIR}/*.c) might be the reason of your issue.
CMake runs some checks on the compiler, and to do so, it generates some .c files and saves them in the build directory
If the build directory is a subdirectory of the main one, the second time that the GLOB_RECURSE runs, it will descend in the build directory, and therefore will add these cmake files in the ${PROJECTNAME}_SOURCES variable.
If your sources are all in the "src" directory, and your headers in the "header" directory, you can use
file(GLOB_RECURSE ${PROJECTNAME}_HEADERS ${CMAKE_SOURCE_DIR}/include/*.h)
file(GLOB_RECURSE ${PROJECTNAME}_SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp)
file(GLOB_RECURSE ${PROJECTNAME}_SOURCES ${CMAKE_SOURCE_DIR}/src/*.c)
And this should fix the issue, because it will not try to recurse in the build directory.