Skip to content

CMake refactor#1805

Merged
jdumas merged 33 commits intomainfrom
jdumas/cmake-refactor
Feb 10, 2022
Merged

CMake refactor#1805
jdumas merged 33 commits intomainfrom
jdumas/cmake-refactor

Conversation

@jdumas
Copy link
Copy Markdown
Collaborator

@jdumas jdumas commented May 10, 2021

Alright, here it is. As part of the efforts towards v3.0.0 described in #1696, this refactors libigl's CMake system to be more modern and maintainable. The new setup is inspired by Lagrange, e.g. how include() + FetchContent is used to download and handle third-party dependencies.

I wrote an upgrade guide > here <, which I will update with final information once we merge this PR.

Highlights

  • CGAL and Boost are now built entirely from source via CMake. This means the CGAL/Cork module will work out of the box under Windows -- no need for a conda virtual environment. On Linux/macOS, the only dependency to install are GMP+MPFR.
  • CMake targets and options have been renamed based on the module category: regular/copyleft/nonfree. This eliminates long module names (igl::open_glfw_imgui) that didn't bring much to the table, in favor of three root classes based on available licenses for each module.
  • There is now a LibiglOptions.cmake sample file at the root of the project repository, which should make it easier to document/update available CMake options.
  • There is now a unique entry point for the project, which is the root CMakeLists.txt. This facilitates maintenance, as before either tutorial/CMakeLists.txt and cmake/libigl.cmake could serve as potential entry points.
  • The default behavior for module compilation is:
    • When compiling libigl on its own, all modules are enabled by default.
    • When compiling libigl as a subproject, all modules are disabled by default.
    • On Linux/macOS, if GMP/MPFR is not installed on the system, shows a warning and disable CGAL/Cork by default.
    • If the user explicitly enables those modules, but they do not have GMP/MPFR installed on the system, CMake configuration will still fail.
  • Big cleanup of the tutorial CMake definitions. With the new setup adding a new tutorial is even easier!
  • Cleaned up dependency setup for imgui/stb (among others)
  • Unit tests have been split into different CMake target, based on which module is tested.
  • Add support for Hunter + install() for the igl::core module (should be the same as before).
  • Use a more generic igl_copy_dll() function to copy GMP/MPFR dlls on Windows.
  • Cleaned up our .gitignore file.
  • Tested on macOS/Windows. Ok looks like I have some issues left to sort out on Windows, shouldn't be to bad.
    --> Looks like we're having compilations issues with Cork on Windows. Cork depends on gmpxx, which is a C++ wrapper around gmp types. The CGAL precompiled gmp libs only come with gmp itself. Thus supporting Cork with gmpxx on Windows would require integrating the mpir fork of gmp. Because this is a lot of work for little value, I vote that we drop support for the cork files altogether. After all we know that there are better alternatives nowadays.

TODO

  • Matlab/Mosek modules are currently missing, because I do not have them setup on my machine/have no way of testing them via Github Actions.
  • OSXFixDylibReferences.cmake is also not used, for the same reason as above (although I am on macOS, I dot not have a setup that needs it).
  • @rbsheth you wrote the initial hunterization of libigl. Could you let me know if you have any concern wrt to this new CMake setup.

@alecjacobson
Copy link
Copy Markdown
Contributor

How dependent are all these changes on each other? Each time I flip through this I get overwhelmed by the number of changes. I'm a bit worried that if we keep it as one larger PR it will never get merged. These changes may have more success if broken down into independent parts.

@jdumas
Copy link
Copy Markdown
Collaborator Author

jdumas commented May 27, 2021

Well the goal of this PR was to refactor and cleanup our CMake build system. There are two parts to this 1) pulling the dependencies, and 2) cleaning up how modules are defined, as well as tutorials/unit tests. It may be a lot of changes, but it's really confined to the CMake scripts (I avoided doing changes to the .cpp unless I had to). I'd rather not do "half-cleanup" for this. Better look at it as a rewrite of the whole CMake build system where everything is new.

Copy link
Copy Markdown
Contributor

@alecjacobson alecjacobson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some initial comments. I think this will take a very long time to sift through everything.

CMakeLists.txt Outdated
endif()

# Check for gmp + mpfr and enable cork / cgal modules accordingly
set(LIBIGL_DEFAULT_CGAL_CORK ${LIBIGL_TOPLEVEL_PROJECT})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this LIBIGL_DEFAULT_CGAL_CORK be something like LIBIGL_DEFAULT_GMP_MPFR ? so it's more clear what it's controlling?

(I'm also not sure what DEFAULT means here.)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have an option LIBIGL_DEFAULT_GMP_MPFR. Here LIBIGL_DEFAULT_CGAL_CORK controls the default value of the options for the CGAL and Cork modules. If GMP and MPFR are not available on the target machine, then I disable the CGAL/Cork modules by default, since CGAL/Cork depend on GMP+MPFR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, and I'm commenting that the name LIBIGL_DEFAULT_CGAL_CORK is confusing since it seems to primarily refer to the presence of gmp/mpfr.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value of LIBIGL_DEFAULT_CGAL_CORK is set based on the presence of gmp/mpfr, but what it is used for is to set the default option for the CGAL and Cork modules. But hey I'm happy to rename it if you prefer.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing though: if libigl is not built as a subproject, LIBIGL_DEFAULT_CGAL_CORK will be OFF. Also on Windows, LIBIGL_DEFAULT_CGAL_CORK will always be ON by default for toplevel project. So if I rename the variable into LIBIGL_GMP_MPFR_AVAILABLE, this would be somewhat misleading (e.g. GMP/MPFR might be available, but because libigl is built as a subproject, it will be set to OFF).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Maybe it makes sense to have a variable that tracks whether GMP_MPFR has been found and then the existing variables for wether building the cork / cgal modules.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a variable that tracks whether GMP_MPFR has been found

What would you use it for? To track whether GMP/MPFR have been found, I would test for the existence of the imported targets gmp::gmp and mpfr::mpfr. Using variables in CMake is kinda brittle so I like to keep it to the bare minimum. But if you want to amend this part of the script to your liking feel free to give it a shot, since I'm not sure what you have in mind.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I can amend it because I don't understand it. What does LIBIGL_DEFAULT_CGAL_CORK mean? LIBIGL I can guess means this is one of our variables, DEFAULT means this is a flag On or Off for a default setting. CGAL_CORK why both? Is this variable the same as LIBIGL_DEFAULT_CGAL AND LIBIGL_DEFAULT_CORK?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it's just a variable name. The "correct" name should be:

LIBIGL_DEFAULT_VALUE_FOR_CMAKE_OPTION_CGAL_AND_CORK_MODULES_BASED_ON_WHETHER_GMP_AND_MPFR_ARE_AVAILABLE

Then I just use this variable twice to set the default value for the following CMake options:

  • LIBIGL_COPYLEFT_WITH_CGAL
  • LIBIGL_COPYLEFT_WITH_CORK

So really this should be invisible to the user. LIBIGL_DEFAULT_CGAL_CORK is just a "local variable", it's not a proper CMake option that the user has to concern themselves with. If the user provides their own value for LIBIGL_COPYLEFT_WITH_CGAL or LIBIGL_COPYLEFT_WITH_CORK, the user-provided option will take precedence.

@@ -0,0 +1,76 @@
# Try to find the GNU Multiple Precision Arithmetic Library (GMP)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow from previous discussions with @jdumas I was under the impression that writing custom Find*.cmake was a no-no these days. This PR adds a lot of custom cmake. Is this really what's expected for a modern cmake build system? Or is it a special case because GMP/MPFR are a pain?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GMP/MPFR are a pain yes. We are not building them from source since they do not use a CMake build system. So the only option is to install via a package manager on macOS/Linux, or download a pre-built dll on Windows (which this find_package() will find).

@@ -0,0 +1,32 @@
# 1. Define module
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These cmake/igl/modules//.cmake files all look roughly the same. Perhaps this can be abstracted into a function rather than copy-pasting files with minor changes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wary of making everything into a function. This file still separates the different parts of defining a libigl module based on:

  1. Module name
  2. Include headers
  3. Target sources
  4. Target dependencies
  5. Unit test definitions

Imho abstracting away some of these steps would make it too much look like "cmake magic" (e.g. where does the include header definition come from?).

if (ImGui::CollapsingHeader("Workspace", ImGuiTreeNodeFlags_DefaultOpen))
{
float w = ImGui::GetContentRegionAvailWidth();
float w = ImGui::GetContentRegionAvail().x;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

candidate for independent PR

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added the IMGUI_DISABLE_OBSOLETE_FUNCTIONS define macro when updating our imgui dependency, which required updating the code accordingly. I could make a separate PR for this but I don't think it's worth the effort (adding IMGUI_DISABLE_OBSOLETE_FUNCTIONS to our current CMake would create conflict, and otherwise the change is not needed).

@jdumas
Copy link
Copy Markdown
Collaborator Author

jdumas commented May 29, 2021

Alright I have renamed nonfree -> restricted + added details in comments, and updated the description in the ".sample" CMake file. Once this is merged I will update instructions on the website accordingly.

@rbsheth
Copy link
Copy Markdown
Contributor

rbsheth commented Jun 25, 2021

I haven't got a chance to review the PR in its entirety but happy to help test as needed.

@jdumas
Copy link
Copy Markdown
Collaborator Author

jdumas commented Jun 27, 2021

I haven't got a chance to review the PR in its entirety but happy to help test as needed.

Thanks! I just want to make sure this is not breaking existing Hunter integration. I don't have much experience packaging libraries with Hunter, and I'm not sure if you use the upstream repo or a clone for the Hunter package. If you have any insight please let me know.

@melMass
Copy link
Copy Markdown

melMass commented Sep 5, 2021

Hey, I'm interested in adding Conan support (#1634) and it seems this PR is almost done and awaits review?

Thanks

@jdumas
Copy link
Copy Markdown
Collaborator Author

jdumas commented Sep 5, 2021

Yes I'm waiting for green light from @alecjacobson and @danielepanozzo, but not sure when it's gonna happen...

@melMass
Copy link
Copy Markdown

melMass commented Sep 25, 2021

Thanks I'll wait for @alecjacobson and @danielepanozzo to chime in!

@jdumas jdumas removed this from the v2.4.0 milestone Feb 10, 2022
@jdumas jdumas changed the title CMake refactor for v3.0.0 CMake refactor Feb 10, 2022
@jdumas jdumas merged commit b0fd49d into main Feb 10, 2022
@jdumas jdumas deleted the jdumas/cmake-refactor branch February 10, 2022 02:58
@alecjacobson
Copy link
Copy Markdown
Contributor

🎉

DavidKorczynski added a commit to DavidKorczynski/oss-fuzz that referenced this pull request Feb 19, 2022
libigl introduced breaking changes in
libigl/libigl#1805 This fixes the OSS-Fuzz set
up.
AdamKorcz pushed a commit to google/oss-fuzz that referenced this pull request Feb 19, 2022
libigl introduced breaking changes in
libigl/libigl#1805 This fixes the OSS-Fuzz set
up.
MartinPetkov pushed a commit to MartinPetkov/oss-fuzz that referenced this pull request Aug 15, 2022
libigl introduced breaking changes in
libigl/libigl#1805 This fixes the OSS-Fuzz set
up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants