Eclipse CDT and CMake + Ninja -- proper project organization - cmake

I have a static library libXY and a program exeA using it. I fail to find a proper project setup which allows me to use ninja from within Eclipse CDT to build only what is needed to build.
So far, I had one project with ninja build files created by cmake which defined several targets which was perfect for building from command line:
build everything if anything changed (aka ninja all)
build libXY if any source files changed (aka ninja libXY)
build libXY if any source files changed and build exeA if any source file changed and link (aka ninja exeA)
I imported the project (created with cmake's Eclipse CDT / Ninja generator) into Eclipse CDT, but there, I could only build everything (ninja all). I was unable to get Ctrl-B to build just the library and the proper target, I was unable to define targets within Eclipse.
As plan B, I created a setup where libXY and exeA are independent projects. I am unable to define the dependency from exeA to libXY so that the library is built automatically if any of its source files changed.
Help! What is the proper project architecture?

Related

CMake force install after add_subdirectory

We are converting a large Makefile based project to a CMake based system. I have numerous dependencies that I need to build prior to building our code. The first three dependencies are build using the following:
add_subdirectory(dependencies/libexpat/expat)
add_subdirectory(dependencies/libuuid-1.0.3)
add_subdirectory(dependencies/log4c-1.2.4)
expat has it's own CMakeLists.txt file and build with no problems. I would like to force expat to install to the staging directory before continuing. For libuuid I am using a ExternalProject_Add and as part of that process it does install into the staging directory.
Then when I build log4c, which needs expat, I can point it to the location of expat. Otherwise I would need to someone get access to the absolutely path for the temporary build location of expat.
I've tried to add the following after add_subdirectory:
add_subdirectory(dependencies/libexpat/expat)
add_subdirectory(dependencies/libuuid-1.0.3)
install(TARGETS expat LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/usr/lib)
add_subdirectory(dependencies/log4c-1.2.4)
Unfortunately CMake will not run expat's install code. How do I force expat to install after building but before it builds the rest of the project?
This looks like the primary use case for ExternalProject_Add, which is best used as a superbuild setup. This means that your top-level project (the "superbuild") does not build any actual code and instead consists only of ExternalProject_Add calls. Your "real" project is added as one of these "external" projects. This allows you to set up the superbuild with all dependencies, ordering, etc.
The workflow is then as follows:
Generate the superbuild project.
Build the superbuild project. This will build and install all dependencies, and also generate (and build) your real project.
Switch to the buildsystem generated for your real project and start doing further development using that. Your dependencies are already correctly set up and installed by the build of the superbuild project in the previous step.

How to include a library using CMAKE in a cross-platform way

I am trying to use the assimp library in a cross platform C++ project. I include the repo as a git submodule, so, effectively, if someone downloads my project they will also download the ASSIMP project.
After I go through the assimp build / CMAKE instructions and (on Linux) type make install and from then on in my project I can use:
target_link_libraries(${PROJECT_NAME} assimp)
However, there is no make install on Windows.
The only other way I have been able to include the library on Linux is to put (in my CmakeLists.txt file):
target_link_libraries(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/build/assimp/code/libassimp.so)
This is not cross platform as it hardcodes the name and location of the .so file which will not work on Windows.
How can I expose the library so that I can do something like target_link_libraries(${PROJECT_NAME} assimp) on all platforms?
My directory tree looks like:
- src
- include
- assimp
- bin
Where the assimp directory in the include directory is the git submodule
I think you're going about this the wrong way. You don't need to build assimp in a separate step from your project, and you don't need to make install to make it available.
There are a number of ways of handling third party dependencies in Cmake, since you've already chosen to submodule the assimp repository, we'll start there. Assuming assimp is located in the root of your repository in a directory called assimp/ this would be a barebones project including it:
cmake_minimum_required(VERSION 3.0)
project(Project myassimpproj)
# include your directories
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
# set any variables you might need to set for your app and assimp
set(BUILD_ASSIMP_TOOLS ON)
set(ASSIMP_BUILD_STATIC_LIB ON)
# add assimp source dir as a subdirectory, effectively making
# assimp's CMakeLists.txt part of your build
add_subdirectory(/path/to/assimp ${CMAKE_BINARY_DIR}/assimp)
add_executable(assimp_target main.cpp)
# be sure to link in assimp, use platform-agnostic syntax for the linker
target_link_libraries(assimp_target assimp)
There may be a better way of phrasing this using generator expressions syntax, but I haven't looked at assimp's CMakeLists.txt to know if it's supported (and this is a more generic way anyway.)
Not every project uses Cmake, so you may not be able to just add_subdirectory(). In those cases, you can effectively "fake" a user call to build them using their build commands on respective platforms. execute_process() runs a command at configure time add_custom_command() and add_custom_target() run commands at build time. You then create a fake target to make integration and cross your fingers they support Cmake someday.
You can also use the ExternalProject commands added to Cmake to create a custom target to drive download, update/patch, configure, build, install and test steps of an external project, but note that this solution and the next download the dependency rather than using the submodule'd source code.
Finally, I prefer to work with prebuilt dependencies, cuts down on build time, and they can be unit tested on their own outside of the project. Conan is an open source, decentralized and multi-platform package manager with very good support for C++ and almost transparent support for Cmake when used the right way. They have grown very stable in the last year. More information on how to use Conan with Cmake can be found here.

Is it possible to build cmake projects directly using MSBuildTools

Currently we are planning to use VS2017 with a cmake project. Inside Visual Studio this works quite like a charm.
Now want to run our builds as part of CI on a dedicated build master running MSBuildTools.
Is it possible to directly run the build using the msbuild command, without creating solution files with cmake? Optimally, I would even use the CMakeSettings.json used from VS2017.
Use the build-tool-mode of CMake for this. It uses the underlying default build tool which is MSBuild for Visual Studio Generators.
From the build directory call:
cmake --build . --target ALL_BUILD --config Release -- /nologo /verbosity:minimal /maxcpucount
and you get a fast, nearly quiet build. To install use INSTALL target, for running your tests if configured use RUN_TESTS target.
Is it possible to directly run the build using the msbuild command, without creating solution files with cmake?
Is it possible to directly run the build using the msbuild command, without creating solution files with cmake?
As far as I know, CMake produces Visual Studio Projects and Solutions seamlessly. So you can produce projects/solutions.
The only tricky part is to remember to make any changes in the cmake files, rather than from within Visual Studio.
In particular, each CMake project will create a Visual Studio solution (.sln file), while all of the CMake targets belonging to that CMake project will appear as Visual Studio projects within the corresponding solution.
CMake Visual Studio
project <-> Solution (.sln)
Target <-> Project (.vcxproj)
You can check cmake-and-visual-studio for more details.
Since MSbuild can build both solution files and project files, so you could also call msbuild INSTALL.vcxproj
Is it possible to even use the CMakeSettings.json used in VS2017?
The answer is yes, check the blog for details.
If your CMake project requires additional settings to configure the
CMake cache correctly, you can customize these settings by creating a
CMakeSettings.json file in the same folder with the root
CMakeLists.txt. In this file you can specify as many CMake
configurations as you need – you will be able to switch between them
at any time.
You can create the CMakeSettings.json file by selecting the Project >
Edit Settings > path-to-CMakeLists (configuration-name) menu entry.

linking failed when building my own project using LLVM

I'm learning to build a llvm project, this is the reference: http://llvm.org/docs/Projects.html. I use the "llvm/projects/sample" directory as the primary project skeleton, and it works. Then I want to build tools from "llvm/examples" to my project, such as Fibonacci, it can't work. I do it this way: first copy the "llvm/examples/Fabonacci" directory to "MyProj/tools" ("MyProj" is top level of my project) and change Makefile to contain Fabonacci target, then configure & make. but the Fabonacci tool seems can't be built. It depends on some libs when linking. So what can I do if I want to build the source code from "llvm/projects/example" in my project?
You need to provide LLVM libraries to linker when building your own project. This means adding some flags, library directories and libraries themselves to link command. Build script probably needs some editing.
llvm-config tool can be used for providing necessary options to compiler/linker. Check documentation and examples.

How to configure Eclipse CDT for cmake?

How to configure Eclipse "Helios" with plugin CDT for cmake?
cmake all
CMake Error: The source directory "D:/javaworkspace/workspace/Planner/Debug/all" does not exist.
Eclipse always wants to use 'all' option and I don't know how to stop its to not use it.
I've seen that in "Build behavior" section, in "Preference" there have been 'all' option. I erased this, but it still works wrong (this same error).
In Eclipse-CDT you do not create cmake projects but you import cmake projects.
This is what you should do:
Say the source of your CMake project named "Planner" is located in D:/javaworkspace/src/Planner
Create a folder (the folders NEED to be parallel to each other): D:/javaworkspace/build/Planner
Go to the folder D:/javaworkspace/build/Planner and run CMake using the Eclipse generator:
cmake ../../src/Planner -G"Eclipse CDT4 - Unix Makefiles"
This will generate the make files for your Planner project.
To import this in Eclipse do the following:
File -> Import -> C/C++ -> Existing code as Makefile project
and select D:/javaworkspace/build/Planner (the build output folder with the make files) as the "Existing Code location"
However, looking at your paths it seems to me that you are working on Windows. In windows CMake can generate Visual Studio projects. If you want to use CMake I suggest first creating a "hello world" project using CMake (remember, Eclipse does not create CMake projects, you have to create a CMakeLists.txt file by hand)
What worked best for me is cmake4eclipse. It's a plugin that is available via the marketplace.
Portions from the cmake4eclipse help text:
CMake for CDT requires an existing C/C++ project to work with. It
allows to use cmake as the generator for the makefiles instead of the
generator built-in to CDT. See Enabling CMake buildscript generation
for details.
To set up a new project with existing source code, please follow these
steps:
Check out your source code.
Open the new C/C++ project wizard ("File" => "New" => "C Project" or "File" => "New" => "C++ Project").
Make sure the project location
points to root directory of your checked out files
For the project
type, select Executable. You may also select Shared Library or Static
Library, it does not matter, that information comes from your
CMakeLists.txt, but CDT requires it. Do not select Makefile project
here!
Finish project creation.
Open the "Project Properties" dialog.
Select the "C/C++ Build" node and the "Builder Settings" tab and make sure Generate Makefiles
automatically is checked.
Select the "Tool Chain Editor" node and
set "CMake Make Builder" as the current builder.
If your top level
CMakeLists.txt does not reside in the root directory of your checked
out files, select the "C/C++ General" "Path and Symbols" node and the
"Source Location" tab. Then adjust the source folder to point to the
directory containing your CMakeLists.txt file. This will tell the CDT
indexer to scan the header files in your project.
Pro Tip: Add a CMakeLists.txt file in the root directory of your checked out files, if you miss the Binaries or Archives folder in the
C/C++ Projects View. Build the project. This will invoke cmake to
generate the build scripts, if necessary, and then will invoke make.
Do not try to import an Eclipse project that you created manually
using cmake -G Eclipse CDT4 - Unix Makefiles, as that will put you on
the classic Makefile project route!
The best thing about this plugin is that it can use the cmake exported compiler options to index your project.
Open the "Project Properties" dialog.
Select the "C/C++ General" node and the "Preprocessor Includes Paths, Macros etc." tab. Select "CMAKE_EXPORT_COMPILE_COMMANDS Parser" and move it to the top of the list.
Hit "OK" to close the dialog. Make sure to trigger one build now and recreate the index.
This fixed all the nasty indexer problems that were annoying me when I only used "CDT GCC Build-In Compiler Settings" and added stuff like "-std=c++14" to "Command to get the compiler specs".
Using CMAKE in Eclipse Makefile project(on win):
1) create new "Makefile Project with Existing Code"
2) modify builder settings(Project Properties->C/C++ Build->Builder Settings):
Build command: cmd /c "mkdir ${PWD} & cd /D ${PWD} && ${CMAKE} -G "Unix Makefiles" ${ProjDirPath} && make"
Build directory: ${workspace_loc:/IoT_SDK}/build/${ConfigName}
That's all!
In addition to accepted answer you should specify eclipse version.
Eclipse Luna (4.4):
cmake -G"Eclipse CDT4 - Unix Makefiles" -D_ECLIPSE_VERSION=4.4 ../../src/Planner
Eclipse Kepler (4.3):
cmake -G"Eclipse CDT4 - Unix Makefiles" -D_ECLIPSE_VERSION=4.3 ../../src/Planner
Another completely different method.
Manually create an empty Eclipse project.
Link source directory via Project Properties -> C/C++ General -> Paths and Symbols -> Source Location.
In the Debug and Release build directories create 'Make Targets' (using the 'Make Targets View'). Leave 'Make Target' field empty and set the 'command' field to cmake -G "Unix Makefiles" <path/to/the/sources>.
When you double-click on the 'Make Target' that you've created, it should trigger cmake invocation inside the Debug/Release dirs.
In 'Project Properties -> C/C++ Build' disable built-in makefile generator.
Now normal build should work. It will also pick up any changes in the CMakeLists.txt files (to the extent that CMake can).
Maybe a more detailed description: https://stackoverflow.com/a/38140914/4742108
Whatever method I have used the external includes has not been indexed.
This is because CMAKE used the "response files" which hides all includes inside those files, instead use it directly (-IPATH_TO_SOME_DIR)
To disable the "response file" I have used following commands:
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES NO)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES NO)
To force the CMAKE to show gcc/g++ execution I have modified the make build target to
"all VERBOSE=1". Note that this is not needed when you are using cmake4eclipse.
I have eclipse in version 2018-12 (4.10.0) with CDT in version 9.6.
This is an old question, but deserves some updates.
First is that the person who made cmake4eclipse added the parsing functionality into CDT. The feature/bug was marked as "Resolved-Fixed" on 2020-08-05 (Aug 5, 2020), so it should go into the version of Eclipse due out next month. See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=559674
The other thing to point out is that you can manually trigger parsing on files:
Configuration Options / Index source and header files opened in editor