norlab-ulaval / libpointmatcher

An Iterative Closest Point (ICP) library for 2D and 3D mapping in Robotics
BSD 3-Clause "New" or "Revised" License
1.61k stars 544 forks source link

MSVC: cannot build and install Release AND Debug versions of the library #459

Open cjamin opened 3 years ago

cjamin commented 3 years ago

Hi,

When I build the INSTALL project in Release or Debug mode, it replaces the pointmatcher.lib which is in install/lib. It should be two different files for Debug and Release, right?

Because of this problem, my own program can only be built in the mode I chose for libpointmatcher.

Any way to fix this? Thanks!

aguenette commented 3 years ago

Hi @cjamin! Actually, there's no way to build and install libpointmatcher in Release and Debug mode separately, but you can use the flag RelWithDebInfo instead, which is a Release built with the Debug's infos.

cjamin commented 3 years ago

Ok, but debugging my program in RelWithDebInfo mode is not as good as in Debug mode. It can be useful when Debug is too slow, but only in this case.

I would be ok if I could build my program in Debug mode linking with the RelWithDebInfo version of libpointmatcher, but I can't. It produces errors related to _ITERATOR_DEBUG_LEVEL and such.

Are you saying there is no way to be able to build my program in Debug mode? Of course, I could rebuild libpointmatcher each time, but it's quite slow!

aguenette commented 3 years ago

Are you saying there is no way to be able to build my program in Debug mode?

Not really, what I was saying is that for the moment, there is no way to install two version of libpointmatcher, i.e. Release and Debug, and be able to link to the right one for your program, i.e. linking with the Release version for your Release version, out of the box. I thought that the flag RelWithDebInfo would be enough, and it's ok if it was not the kind of solution you were looking for.

That being said, I may have another solution for you, but keep in mind that I haven't test it, so it's possible that it doesn't work:

  1. Create a build directory for each version that you want a build type for, e.g. build-release, build-debug for libpointmatcher and for your project.

  2. Then, for each libpointmatcher's build directory, configure cmake with the build type at the end of the INSTALL_LIB_DIR or CMAKE_INSTALL_LIBDIR flag (not sure which one 🙄). On linux, it would be something like that: /lib/pointmatcher/debug for the Debug config.

  3. Then, you will have to change the line 503 in libpointmatcher's CMakeLists.txt file, which is :

    install(EXPORT ${PROJECT_NAME}-config DESTINATION share/${PROJECT_NAME}/cmake)

    to this:

    install(EXPORT ${PROJECT_NAME}-config DESTINATION share/${PROJECT_NAME}/cmake/${CMAKE_BUILD_TYPE})

  4. Finally, for each build directory in your project, specify the libpointmatcher_DIR so it point to the right location. On linux, it would be something like this: /usr/local/share/libpointmatcher/cmake/debug for the Debug config.

I will eventually test it, but if this doesn't work, you can skip the parts where you modify the cmake's flags and just use different build directory for each build type and do reinstall the version that you need when you need it. It will avoid you to completely rebuild the library every time. 😅

cjamin commented 3 years ago

Hi, Thank you very for taking the time to write these instructions! I will try this. Actually, I'm wondering if the modification of the libpointmatcher's CMakeLists.txt is really necessary. Maybe I could specify a different CMAKE_INSTALL_PREFIX for the Debug and the Release version?

aguenette commented 3 years ago

No problems! 😄

Maybe I could specify a different CMAKE_INSTALL_PREFIX for the Debug and the Release version?

You could do that, but if you do, I suggest you to specify a path in your user repository, e.g. /home/username/.libpointmatcher/your_build_type on Linux. It's just a suggestion, there's probably a better way to do that and I would need to investigate a little bit more into that.

cjamin commented 3 years ago
4\. Finally, for each build directory in your project, specify the `libpointmatcher_DIR` so it point to the right location. On linux, it would be something like this: `/usr/local/share/libpointmatcher/cmake/debug` for the Debug config.

I don't understand this part of your method: this seems to suggest that I create two different projects for my program, because I can't specify two different values of libpointmatcher_DIR otherwise. But if I really create two different projects, then I end up doing what you propose at the end: "just use different build directory for each build type". What did I miss?

traversaro commented 3 years ago

I think you can configure libpointmatcher's CMake by passing -DCMAKE_DEBUG_POSTFIX:STRING=d so that the Debug libraries will contain a d in the name so that they will not overwrite the Release libraries.

aguenette commented 3 years ago

@cjamin I'm sorry if my instructions were a bit confusing. Instead, I will give it to you as a series of steps in the command line.

First, go in libpointmatcher's directory and run the following command lines (If you already had created these directories, just delete them):

mkdir build-release && cd build-release
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
sudo make install

cd ..
mkdir build-debug && cd build-debug
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEBUG_POSTFIX:STRING="-debug" ..
make -j$(nproc)
sudo make install

Then, do these steps in your project directory:

mkdir build-release && cd build-release
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)

cd .. && mkdir build-debug && cd build-debug
cmake -DCMAKE_BUILD_TYPE=Debug  ..
make -j$(nproc)

That's it! This will configure and build a directory for each type of build that you want. If you want to make sure that your project is linking to the right version of libpointmatcher, add the VERBOSE=1 flag to the make command, like this: make -j$(nproc) VERBOSE=1. Also, feel free to change the Debug postfix for something else.

Using a different directory for your different build type is something really useful as it avoid you to rebuild the library everytime you want to switch from a Release build to a Debug build and vice-versa. Also, thanks to @traversaro for pointing out the CMAKE_DEBUG_POSTFIX flag, which make the whole thing much simpler. That's really appreciated! 😄

I've just tested it and it worked for me, I hope it will work for you too. 😃 And, I also hope that it helps you understand a little bit more what I meant by using a different directory for different build type.