ITK installation and sample program - c++

I am new to ITK and I did the following step to install ITK and use it to programme in VS2010
Downloaded ITK 4.3.1 and build it with CMAKE
The build was successful and I had a lib->Debug folder containing the libs.
Added the bin folder path to environmental vairable path.
Following is my simple code...
#include <iostream>
#include <Core/Common/include/itkImage.h>
using namespace itk;
using namespace std;
int main()
{
return 0;
}
the above code returns
Cannot open include file: 'itkConfigure.h'
I tried searching for that header but no luck. However in C:\InsightToolkit-4.3.1\Modules\Core\Common\src I found itkConfigure.h.in file. I am really clueless about how to go about this .in file. Any help is most welcome..

The easiest way to set up your project is to use CMake again. Try creating a project with just a CMakeLists.txt and main.cpp. The CMakeLists.txt should have something like:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(ItkTest)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
add_executable(MyTest main.cpp)
target_link_libraries(MyTest ITKCommon)
So say you create these 2 files in a dir called ItkProject, then from a Visual Studio Command Prompt just do:
cd <path to ItkProject>
mkdir build
cd build
cmake .. -DITK_DIR="<path to build dir of ITK>"
The <path to build dir of ITK> is where you ran CMake from to configure the ITK project. It will contain the ITK.sln file, but critically it should also contain a file called ITKConfig.cmake. It is this file which is searched for in the cmake command find_package(ITK REQUIRED) - if CMake can't find it the configuring will fail.
Once that's been found, it sets a bunch of CMake variables which you can then use in your own CMakeLists.txt, including ITK_USE_FILE.
When you then invoke include(${ITK_USE_FILE}), this goes on to set up things like your includes paths, library search paths, and compiler flags. The path <path to ItkProject>/Core/Common/include will be added to the includes dirs, so in your main.cpp, you just need to do:
#include <Core/Common/include/itkImage.h>
#include "itkImage.h"
Anyway, the end result after running CMake should be solution file <path to ItkProject>\build\ItkTest.sln which is set up ready to use ITK.

I checked \ItkConfig.cmake and paths defined there should match physical paths, this is the case if ITK build has been untouched (directory wasn't renamed).
# The ITK source tree.
# For backward compatibility issues we still need to define this variable, although
# it is highly probable that it will cause more harm than being useful.
# Use ITK_INCLUDE_DIRS instead, since ITK_SOURCE_DIR may point to non-existent directory
IF(NOT ITK_LEGACY_REMOVE)
SET(ITK_SOURCE_DIR "C:/ITK320")
ENDIF(NOT ITK_LEGACY_REMOVE)
# The ITK include file directories.
SET(ITK_INCLUDE_DIRS "C:/ITK320-build;C:/ITK320/Code/Algorithms;C:/ITK320/Code/BasicFilters;C:/ITK320/Code/Common;C:/ITK320/Code/Numerics;C:/ITK320/Code/IO;C:/ITK320/Code/Numerics/FEM;C:/ITK320/Code/Numerics/NeuralNetworks;C:/ITK320/Code/SpatialObject;C:/ITK320/Utilities/MetaIO;C:/ITK320/Utilities/NrrdIO;C:/ITK320-build/Utilities/NrrdIO;C:/ITK320/Utilities/DICOMParser;C:/ITK320-build/Utilities/DICOMParser;C:/ITK320-build/Utilities/expat;C:/ITK320/Utilities/expat;C:/ITK320/Utilities/nifti/niftilib;C:/ITK320/Utilities/nifti/znzlib;C:/ITK320/Utilities/itkExtHdrs;C:/ITK320-build/Utilities;C:/ITK320/Utilities;C:/ITK320/Code/Numerics/Statistics;C:/ITK320/Utilities/vxl/v3p/netlib;C:/ITK320/Utilities/vxl/vcl;C:/ITK320/Utilities/vxl/core;C:/ITK320-build/Utilities/vxl/v3p/netlib;C:/ITK320-build/Utilities/vxl/vcl;C:/ITK320-build/Utilities/vxl/core;C:/ITK320-build/Utilities/gdcm;C:/ITK320/Utilities/gdcm/src")
# The ITK library directories.
SET(ITK_LIBRARY_DIRS "C:/ITK320-build/bin")

Related

Undefined reference errors when trying to compile and simple ImageMagick program

I've been searching for a solution to this problem for a long time to no avail.
I am trying to compile this simple program:
#include <iostream>
#include <Magick++.h>
#include <Magick++/Image.h>
using namespace std;
using namespace Magick;
int main(int argc,char **argv) {
InitializeMagick("D:\\Programming\\CPPProjects\\NoteScripts\\Dependencies\\magick\\include");
Image image;
// image.read("arch");
// image.write("test.png");
}
Upon building, I get the following error:
CMakeFiles\main.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x1c): undefined reference to `Magick::InitializeMagick(char const*)'
CMakeFiles\main.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x28): undefined reference to `Magick::Image::Image()'
CMakeFiles\main.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x34): undefined reference to `Magick::Image::~Image()'
collect2.exe: error: ld returned 1 exit status
From what I can tell, this is a linker error but I have no idea where I am going wrong with linking the libs needed.
I installed ImageMagick on Windows 10 from the ImageMagick downloads page with this installer: ImageMagick-7.1.0-50-Q16-HDRI-x64-dll.exe
I then copied the lib files from the lib folder under the installation directory into my project and then copied the include folder under the installtion directory into my project.
Here is what the project hierarchy looks like (Source Directory is NoteScripts):
My CMakeLists.txt consists of:
cmake_minimum_required(VERSION 3.10)
set( CMAKE_CXX_COMPILER "C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/g++.exe")
set( CMAKE_C_COMPILER "C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/gcc.exe" )
# set the project name
project("Notes")
include_directories(D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/include)
# add the executable
add_executable(main main.cpp)
target_link_libraries(main D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/lib/CORE_RL_Magick++_.lib)
target_link_libraries(main D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/lib/CORE_RL_MagickCore_.lib)
target_link_libraries(main D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/lib/CORE_RL_MagickWand_.lib)
If I comment out lines 9 and 10 where InitializeMagick() is called and where Image image is declared, the program compiles without error. I'm also aware that the order of the static libs listed out matters but trying out multiple combinations has resulted in the same error. I have also verfied the dependency order by sifting through the original source code and the reference path is Magick++ -> MagickCore -> MagickWand.
I am relatively new to the process of adding external dependencies to my C++ projects so this is unfamiliar territory (coming from languages with clean package managers). Any help as to how to fix this issue is greatly appreciated!
The typical (and easiest) way of handling dependencies in CMake is using its find_package command:
find_package(ImageMagick REQUIRED COMPONENTS MagickCore MagickWand Magick++)
// ...
target_link_libraries(main ${ImageMagick_LIBRARIES})
This method is available for ImageMagick with your CMake version. I'm not familiar with CMake on Windows, but find_package by default searches a number of standard (system) locations for the package's files. Since you have a custom setup, it should also be possible to specify a nonstandard search prefix to the command. Additionally, you could download external dependencies in a portable way with the FetchContent commands.
First of all, it is a pain to setup this thing if you are a newbie like me.
Now to the steps to dynamically link imagemagick libs with your C app:
go to https://github.com/ImageMagick/ImageMagick-Windows and follow the instructions there (Install Visual Studio dependencies - Clone the dependencies - Build configure.exe- Build ImageMagick)
in the step Build configure.exe, when running configure.exe, keep the default option selected when asked about the output library type (keep it set to dynamic)
in the Build ImageMagick step, when you open VisualDynamicMT.sln in visual studio, before you start the build, select all the solutions in the project, and right-click -> properties -> General -> C Language Standard -> choose Default (Legacy MSVC). After that, click on the top-most solution that contains all the other 196 solutions, and build it. watch the console for errors, I didn't get any errors with the configuration above.
After the latter step, go the VisualMagick folder (created from steps before), and you will see lib folder and bin folder. You're done, your dlls are in bin and your .lib file are in bin folder. Note that these files will be corresponding to build or release environments depending on what you selected in visual studio at the build step.
How do you use imagemagick now in your project regardless if you have imagemagick app installed on your pc or not? Lets create a new project in vscode, call it demo.
Create this project structure:
inside src you will put your C code.
inside deps create ImageMagick/lib and ImageMagick/bin and ImageMagick/include
inside ImageMagick/include place the same include files you said you got in your question.
inside ImageMagick/lib place the .lib files you got from above
inside ImageMagick/bin place the .dll files you got from above
now add this to your CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(demo-app C)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
file(GLOB SOURCE_FILES src/*.c)
add_executable(demo ${SOURCE_FILES})
include_directories(src)
# ImageMagick
if(WIN32)
add_definitions( -DMAGICKCORE_QUANTUM_DEPTH=16 )
add_definitions( -DMAGICKCORE_HDRI_ENABLE=0 )
include_directories(deps/ImageMagick/include)
target_link_directories(demo PRIVATE deps/ImageMagick/lib)
file(GLOB IMAGEMAGICK_LIBS deps/ImageMagick/lib/*.lib)
target_link_libraries(demo
"${IMAGEMAGICK_LIBS}"
)
add_custom_command(TARGET demo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/deps/ImageMagick/bin"
$<TARGET_FILE_DIR:demo>)
endif()
(The add_custom_command will copy the dlls to your executables path after every build)
Now write some magick code in you src directory.
ctrl + shift + A -> CMake select kit -> choose the Visual Studio community 2022 release -amd64 or change to what fits you if it doesn't work
ctrl + shift + A -> CMake Clean Rebuild
ctrl + shift + A -> CMake run without debugging

Facing problems in my first time handling CMake, Third party(header only) libraries

I want to use the following library
https://github.com/gmeuli/caterpillar
It's documentation says that it's a header-only library, and that I should "directly integrate it into my source files with #include <caterpillar/caterpillar.h>." It also depends on a few other libraries, one of which I need to use directly as well.
So far I have done the following:
create cmake project to make an 'executable' (with the vscode extension)
created a 'lib' folder, inside which I did
git clone https://github.com/gmeuli/caterpillar
Then, I did include_directories(lib) in my cmake file.
But #include <caterpillar/caterpillar.h> doesn't quite work in my singular main.cpp file.
I played around with various CMake functions, and it either gave the error "No such file or directory" regarding caterpillar/caterpillar.h itself, or it gave "cannot open source file... dependent of caterpillar/caterpillar.h" depending on how I messed with the cmake file.
For reference:
cat ~/project/main.cpp
#include <caterpillar/caterpillar.hpp>
#include <lorina/lorina.hpp> //how do I include this ? it's in the lib folder of caterpillar itself, or do I need to have a copy of it in my lib folder too
int main()
{
// stuff in lorina:: namespace
// stuff in caterpillar:: namespace
return 0;
}
cat ~/project/CMakeLists.txt
include_directories(lib)
//... rest is stuff like CXX standard, etc etc
tree ~/project
main.cpp
lib/
caterpillar/
build/
cmake generated stuff
CMakeLists.txt
Firstly, modern cmake recommends target_include_directories() instead of old include_directories() for better scope management.
Actually <caterpillar/caterpillar.hpp> is not in $PROJECT_SOURCE_DIR/lib directory. That's why your code not works.
CMakeLists example:
cmake_minimum_required(VERSION 3.22)
project(myproject)
set(CMAKE_CXX_STANDARD 17)
add_executable(my_project main.cpp)
target_include_directories(my_project PRIVATE ${PROJECT_SOURCE_DIR}/lib/caterpillar/include)
# project_src_dir/lib/catepillar/include/ is the directory where you find the headers like <catepillar/catepillar.hpp>
target_include_directories(my_project PRIVATE ${PROJECT_SOURCE_DIR}/lib/caterpillar/lib/lorina)
caterpillar's document describes how to include their headers in a traditional style, assuming the readers could understand this and decide where to put the headers themselves. (which means you don't need the whole git repo but only the "include" dir.)
For this specific problem, the library has provided a detailed CMakeLists.txt for users to include:
cmake_minimum_required(VERSION 3.22)
project(my_project)
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(lib/caterpillar)
# this works because "project_src_dir/lib/catepillar/CMakeLists.txt" exists.
add_executable(my_project main.cpp)
target_link_libraries(my_project PRIVATE caterpillar)
# you need to tell cmake to add all catepillar settings into your project

Installing spdlog by copying contents of include directory

I'm trying to use spdlog as a logging library, but I do not want to use my package manager (apt) to install it. I have copied the spdlog directory under include to the root of my project directory, but when I try to compile I get include errors because the #include directives in the spdlog headers are all absolute (relative to the project root), instead of relative, gcc cannot find the files.
0:10: fatal error: spdlog/common.h: No such file or directory
#include "spdlog/common.h"
Short of changing all the includes in the spdlog library to relative, how can I use spdlog in my project? I'm also using CMake to compile my project; I have a build directory in my project root and from within it I call cmake .. and then make to compile; is there something I need to add to my CMakeLists.txt file to include spdlog?
You need to add the project root directory into the cmake include_directories, like this:
include_directories(
/absolute/path/
)
Or in the project root directory, edit CMakeLists.txt and add this:
include_directories(
.
)

Link to static library by cmake

I have a project C++ using libnuma library. Because I don't have permission to install libnuma in the root system, so I have to install it in folder of user: /home/khangtg/opt. This folder contains 2 main folders:
Folder include contains: numacompat1.h, numa.h, numaif.h
Folder lib contains: libnuma.a, libnuma.la, libnuma.so, libnuma.so.1, libnuma.so.1.0.0
Now, I have a file .cpp include libnuma library:
#include <numa.h>
and I build the project by file CMakeLists.txt with content:
add_library (common Bigraph.cpp AdjList.cpp Vocab.cpp NumaArray.cpp clock.cpp)
set (LINK_LIBS ${LINK_LIBS} common gflags numa )
add_executable (warplda main.cpp lda.cpp warplda.cpp)
add_executable (format format.cpp)
target_link_libraries (warplda ${LINK_LIBS})
target_link_libraries (format ${LINK_LIBS})
After run cmake command, I get some error that is "can not include numa.h".
So, how can I fix this error and build the project by cmake. Many thanks!
you want to set the link_directories to include the directory of the libraries. More can be found in the cmake docs. This tells the linker where to look for the libraries.
It should probably look something like this
link_directories(/home/khangtg/opt/lib)
Also add the include directories command from this documentation.
This will look like this
include_directories(/home/khangtg/opt/include)
This might be useful to add to your cmake build file:
include_directories("/home/khangtg/opt/include")
From: cmake tutorial
You may also want to change the include to :
#include "numa.h"

CMake and external dependency

I'd like to add an external dependency to my project. The one I'm trying to add is the Leptonica library as a submodule.
My project has the following directory structure:
|root
CMakeLists.txt
|-bin
|-build
|-buildsystem
|-executable
|-leptonica
|--CMakeLists.txt
|--cmake
|---Configure.cmake
|-production
In my root CMakeLists.txt file I added ADD_SUBDIRECTORY(${ROOT_DIR}/leptonica)
Unfortunately, CMake is not searching for Configure.cmake in the proper directory:
CMake Error at leptonica/CMakeLists.txt:107 (include):
include could not find load file:
Configure
CMake Error: File
<root>/cmake/templates/LeptonicaConfig-version.cmake.in does not exist.
CMake Error at leptonica/CMakeLists.txt:113 (configure_file):
configure_file Problem configuring file
When I build the project by myself, everything goes fine. In my opinion, the problem is with CMAKE_SOURCE_DIR. When using add_subdirectory it has the value of ROOT CMake instead ROOT/leptonica, so it's searching the wrong paths - as you can see in Leptonica CMake, it's used to determinate paths of its files.
What should be the proper way to fix this - should I set CMAKE_SOURCE_DIR to ROOT/leptonica just before calling add_subdirectory and set it back when it's finished, or does some other, more elegant solutions exist?
Not every CMake project is suitable for inclusion via add_subdirectory.
Among those are projects which uses CMAKE_SOURCE_DIR or CMAKE_BINARY_DIR variables.
However, inclusion via ExternalProject_Add (optionally wrapped with execute_process) always works.
Modifying variable CMAKE_SOURCE_DIR (and CMAKE_BINARY_DIR too) is a bad idea: this variable should be changed only by CMake itself. Otherwise you may get weird errors.
Instead, you may replace (automatically, with some script) all references to the variable with another variable, which is not used in the project. This new variable you may safely set before stepping into the subproject.
${CMAKE_SOURCE_DIR} and ${CMAKE_BINARY_DIR} are set relative to the top-level CMakeLists.txt. If you need something relative to your current CMakeLists.txt (leptonica), use ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR}.
If you're having trouble finding a cmake file like LeptonicaConfig-version.cmake.in, try appending the appropriate directory to ${CMAKE_MODULE_DIR}.
list(APPEND ${CMAKE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates)
I prefer to use ${CMAKE_CURRENT_SOURCE_DIR} over ${CMAKE_SOURCE_DIR} any day because using the latter will break your build if you try to integrate it into a super-build later. If I need to pass my current top-level directory to subdirectories, then I do the following and use that later down the chain.
set( LEPTONICA_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )