Can I make a CMake target dependent upon a target in another CMake project? - cmake

I have two separate projects, but one of them must now incorporate aspects of the other, including the generation of some code, which done by a Python script which is called by CMake.
Here is my project structure:
repo/
├── project_top/
│ ├── stuff_and_things.cpp
│ └── CMakeLists.txt
│
└── submods/
└── project_bottom/
├── CMakeLists.txt
└── tools/
├── build_scripts
│ └── cmake_bits.cmake
└── generator
└── gen_code.py
In repo/submods/project_bottom/tools/build_scripts/cmake_bits.cmake there is a macro set_up_additional_targets(), which includes a custom target which runs repo/submods/project_bottom/tools/generator/gen_code.py in that directory. This is based on project_bottom being its own project.
add_custom_target(gen_code
COMMAND echo "Generating code"
COMMAND python3 gen_code.py args
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tools/generator
)
Now, I need to make a new target in project_top dependent upon the gen_code target in project_bottom. How do I do this? The gen_code target needs to be run as part of the project_top build, but within the context of project_bottom, because for that target, ${CMAKE_CURRENT_SOURCE_DIR} needs to be repo/submods/project_bottom, not repo/project_top.

Related

How to add include_directory in simple CMake Project

I have CMake project whose directory structure is as follows:
├── build
├── CMakeLists.txt
├── src
│   ├── CMakeLists.txt
│   ├── headers
│   │   └── utility.h
│   └── main.cpp
└── tests
├── CMakeLists.txt
├── testfeature_a
│   ├── CMakeLists.txt
│   └── test_me.cpp
└── test_main.cpp
In test_me.cpp I wanted to include utility.h as I wanted to test functions defined there. So I did #include "headers/utility.h" and in testfeature_a CMakeLists.txt I did this:
file(GLOB SRCS *.cpp)
ADD_EXECUTABLE(testfeature_a ${SRCS})
include_directories(src/headers)
TARGET_LINK_LIBRARIES(
testfeature_a
libgtest
libgmock
)
add_test(NAME testfeature_a
COMMAND testfeature_a)
But the make fails with the error message fatal error: headers/utility.h: No such file or directory.
How can I include the headers directory in test_me.cpp
Your path in include_directories() may be incorrect. Here are two things that you could check
The file seems to be the CMakeLists.txt in tests-folder so you need to go up one folder before you can go to src-folder, i.e. include_directories(../src/headers).
You repeat the headers-folder in the #include "headers/utility.h" when you have already specified it in include_directories(src/headers). Either use #include "utility.h" in cpp-file or include_directories(src) in CMakeLists.txt.
Other option is that you don't need to specify the headers-folder in the CMakeLists.txt at all. You can simply use #include "path/to/your/file.h without any other configuration.
For debugging your path in the CMakeLists.txt you can call message-function, e.g. message(${your_path}), so it's printed when executed and you can check if it's correct.
In addition you can use CMake built-in variables such as CMAKE_CURRENT_SOURCE_DIR and CMAKE_SOURCE_DIR, e.g. include_directories(${CMAKE_SOURCE_DIR}/src/headers)

CMake error : "include could not find load file GoogleTest"

I have a problem with adding googletests to CMakeLists.txt.
The problem is "Error:include could not find load file:
GoogleTest".
I have installed google tests using the commands:
sudo apt-get install libgtest-dev
sudo apt-get install cmake # install cmake
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp *.a /usr/lib
These commands I took from here.
There is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.6.2)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_STANDARD 17)
project(compiler)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
find_package(FLEX REQUIRED)
FLEX_TARGET(lexer src/lexer.fl ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp)
find_package(GTest REQUIRED)
include(GoogleTest) <- There is a problem!
add_executable(run_tests src/tests/test.cpp src/main.h ${FLEX_lexer_OUTPUTS})
target_include_directories(run_tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(run_tests ${GTEST_LIBRARIES} stdc++fs)
#gtest_add_tests(TARGET run_tests)
add_executable(compiler src/main.h src/main.cpp src/common.h ${FLEX_lexer_OUTPUTS})
I will be really appreciate if you give me an advice!
If you already got libgtest installed, just add following in your CMakeLists.txt:
target_link_libraries($YOUR_TARGTET gtest)
But! I think you made it too complicated.
It's better to include the googletest source code directlly into your project as a third party library. I will go here this way here and after.
As you involved 'apt-get' in your code example, I assume you are on Debian or Debian decendants. Well, of caurse actually it does not matter which OS you are on.
Clone the googletest source code(check previous for link) into your project, add following into your main CMakeLists.txt:
add_subdirectory(googletest)
add following into sub-cmake projects where you are going to need gtest:
include_directories(${PARENT_PATH_OF_GTEST}/googltest/googltest/include)
# ...
target_link_libraries($YOUR_TARGET gtest)
e.g.
Let's say you have a project with following structure:
.
├── assets
│   └── ...
├── bin
│   ├── CMakeLists.txt
│   └── ...
├── CMakeLists.txt <== Your main CmakeLists.txt
├── src
│   ├── CMakeLists.txt
│   └── ...
├── tests <== Test cases
│   ├── CMakeLists.txt
│   └── ...
└── third_party
├── CMakeLists.txt
├── googletest <=== gtest
└── ...
In your main CMakeLists.txt, you should have:
add_subdirectory(tests)
add_subdirectory(third_party)
# ...
In the third_party CMakeLists.txt:
add_subdirectory(googletest)
# ...
In the tests CMakeLists.txt:
include_directories(${CMAKE_SOURCE_DIR}/third_party/googltest/googltest/include)
# ...
add_executable(my_test...)
target_link_libraries(my_test gtest)
# ...
A better example
Here is a video example for Gtest in CLion from Jetbrains. As CLion actually bases on CMake, so it also clearlly shows you how to integrate GTest into CMake.
Google Test support in CLion

NSIS - check if process exists (nsProcess not working)

For my NSIS uninstaller, I want to check if a process is running. FindProcDLL is not working under Windows 7 x64, so I tried nsProcess.
I've downloaded the version 1.6 from the website: http://nsis.sourceforge.net/NsProcess_plugin
If I start the nsProcessTest.nsi in the Example folder, I get the following errors:
Section: "Find process" ->(FindProcess)
!insertmacro: nsProcess::FindProcess
Invalid command: nsProcess::_FindProcess
Error in macro nsProcess::FindProcess on macroline 1
Error in script "C:\Users\Sebastian\Desktop\nsProcess_1_6\Example\nsProcessTest.nsi" on line 14 -- aborting creation process
This is line 14 of the example script:
${nsProcess::FindProcess} "Calc.exe" $R0
Do somebody know what is wrong? How can I check if a process is running with NSIS?
NSIS does not find the plug-in, so make sure you copied its files to the correct folder.
NSIS 2.x:
NSIS/
├── Include/
│ └── nsProcess.nsh
└── Plugins/
└── nsProcess.dll
NSIS 3.x:
NSIS/
├── Include/
│ └── nsProcess.nsh
└── Plugins/
├── x86-ansi/
│ └── nsProcess.dll
└── x86-unicode/
└── nsProcess.dll
The file inside Plugins\x86-unicode is nsProcessW.dll renamed to nsProcess.dll (blame the author for making it overly complicated!)
More generally, refer to How can I install a plugin? on the NSIS Wiki.

cmake can't find the depending library

I have a demo project which rely on a logger library, The file structure of the relevant files are listed as below:
.
├── FancyLogger
│   ├── CMakeLists.txt
│   ├── FancyLogger.cpp
│   ├── FancyLogger.h
│   ├── bin
│   │   └── libFancyLogger.a
└── HelloClion
├── CMakeLists.txt
├── helloclion.cpp
I have build a static library named as libFancyLogger.a in the ./FancyLogger/bin directory.
My CMakeFiles of the project HelloClion is listed as below:
cmake_minimum_required(VERSION 3.3)
project(HelloClion)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
get_filename_component(CODE_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
set(SOURCE_FILES helloclion.cpp)
add_executable(HelloClion ${SOURCE_FILES})
include_directories(${CODE_ROOT}/FancyLogger)
link_directories(${CODE_ROOT}/FancyLogger/bin)
target_link_libraries(HelloClion FancyLogger)
But the linker complains that library not found for -lFancyLogger, I don't know how to fix this, please help.
I seems to find out why. ;)
In the cmake documentation:https://cmake.org/cmake/help/v3.0/command/link_directories.html
link_directories(directory1 directory2 ...)
Specify the paths in which
the linker should search for libraries. The command will apply only to
targets created after it is called.
The doc says, the command only applys to targets created after it is called. So I just need to move link_directories(${CODE_ROOT}/FancyLogger/bin) to some position in front of the add_executable(HelloClion ${SOURCE_FILES}) command.
Problems solved!

No tests found when using gtest with cmake/ctest

I have a project with the following structure:
linalg
├── build
├── CMakeLists.txt
├── docs
│   └── Doxyfile
├── include
│   └── linalg
│   └── vector3.hpp
├── src
│   ├── CMakeLists.txt
│   └── linalg
│   └── vector3.cpp
└── test
├── CMakeLists.txt
└── linalg
└── test_vector3.cpp
The file test_vector3.cpp is a gtest unit test file which provides two simple tests. The top level CMakeLists.txt simply sets up the includes and adds the src and test subdirectories:
cmake_minimum_required(VERSION 2.8)
project(linalg)
include_directories(include)
add_subdirectory(src)
add_subdirectory(test)
The src/CMakeLists.txt file compiles vector3.cpp into a static library:
cmake_minimum_required(VERSION 2.8)
add_library(linalg linalg/vector3.cpp)
The test/CMakeLists.txt file is based on the example provided in /usr/share/cmake-2.8/Modules/FindGTest.cmake:
cmake_minimum_required(VERSION 2.8)
enable_testing()
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(test_vector3 linalg/test_vector3.cpp)
target_link_libraries(test_vector3 linalg ${GTEST_BOTH_LIBRARIES} pthread)
add_test(test_vector3 test_vector3)
I then run the following:
cd build
cmake ..
make
I get the liblinalg.a library compiled correctly in to build/src and I get the test_vector3 executable compiled correctly in to build/test. I can run the test_vector3 executable and I get the output from googletest saying that all tests have passed, however if I run make test I get no output whatsoever and if I run ctest .. I get a message saying:
Test project /home/ryan/GitHub/linalg/build
No tests were found!!!
Is there something I am missing? Or have I just misunderstood how ctest works with gtest?
The crux of the problem is that enable_testing should be called from your top-level CMakeLists.txt in this case. Adding include(CTest) to your top-level CMakeLists.txt should fix this for you.
This would allow you to remove the enable_testing call in test/CMakeLists.txt, since the CTest submodule calls enable_testing internally.
Just to update this.
cmake in version 3.9 added support for GoogleTest integration with CTest.
So you can now get CTest to scrape all of the test macros in your test executable, not just the whole executable.
Example here:
https://gist.github.com/johnb003/65982fdc7a1274fdb023b0c68664ebe4