Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for replacing cmake #450

Closed
3 tasks done
andlabs opened this issue Dec 31, 2018 · 37 comments
Closed
3 tasks done

Tracking issue for replacing cmake #450

andlabs opened this issue Dec 31, 2018 · 37 comments
Milestone

Comments

@andlabs
Copy link
Owner

andlabs commented Dec 31, 2018

cmake has been headache after headache; see https://github.com/andlabs/libui/issues?utf8=%E2%9C%93&q=label%3A%22cmake+dumbness%22+ for a list of particular incidents; there's probably more than this, even

  • Find a replacement
  • Do the replacement
  • Make sure it works with CI

Requirements, indicating how hard or soft they are:

  • [HARD] Must support both MSVC and MinGW on Windows
  • [HARD] Must support both static and shared library output, on all platforms in all toolkits (except MinGW shared libraries, which libui does not yet support building as)
  • [HARD] Must either support custom .rc files on Windows or provide a supported way of turning them off (even MinGW-w64 has started trying to be "helpful" in a way that makes .exe.manifest files impossible; see this)
  • [MEDIUM-HARD] Must be as easy to configure a build as mkdir build; cd build; tool option=setting option2=setting2 and must be as easy to clean up as rm -rf build
  • [MEDIUM] Must either be explicit about what it's doing or give me a supported way of turning off automatic insertions I don't want
  • [MEDIUM] Should not have any undocumented magic build configurations I don't know about that will break for the one person who tries to use them
  • [MEDIUM] Should not increase the amount of effort required to build libui from source by much; this means being light and generally uncontroversial on dependencies
  • this list is probably incomplete

Suggested by others for replacement:

  • waf (requires python at runtime)
  • [the winner] meson (requires python and ninja at runtime)

Other possibilities, in order of decreasing likelihood:

  • a custom thing entirely
  • scons (requires python at runtime)
  • bazel (requires java at runtime)
  • gn (not sure what it depends on at runtime, but there does not seem to be an easily-accessible place for the official one, and lots of forks on github)

Suggestions from below:

  • buck (basically facebook's version of bazel; requires java at runtime)

Non-starters:

  • autotools (I'm here to decrease headache, not increase headache)
@andlabs andlabs added this to the Alpha 5 milestone Dec 31, 2018
@franko
Copy link

franko commented Dec 31, 2018

My humble suggestion is to adopt Meson. The experience that I have is that it is much simpler than CMake and does out-of-the-box the right thing.

In addition it has a good documentation, an active and very helpful community of developers. The project progress steadily and any issue you may point out is rapidly addressed.

@kubastick
Copy link

What about buck build system? https://buckbuild.com/

@profi200
Copy link

profi200 commented Jan 1, 2019

I would strongly advise against choosing some random build system no one heard about. It will give you just as much headaches as cmake does. Stick with autotools or good old make. The former will work practically everywhere.

@andlabs
Copy link
Owner Author

andlabs commented Jan 1, 2019

The reason for choosing cmake in the first place was because I was using Makefiles at first and it turned out to work for me and only me; everyone else either ran into weird problems or had no idea how to set up GNU make for Windows (and I wasn't interested in maintaining multiple separate Makefiles just so I could use nmake for MSVC since the two have very incompatible syntax, unless there's a workaround I could use to keep only the build rules separate?).

I am not even considering autotools, sorry.

@msink
Copy link
Contributor

msink commented Jan 2, 2019

IMHO the only well supported alternative to CMake is Meson.
My impression two years ago was very positive: https://github.com/msink/hello-c

And BTW, just noticed that meson itself recently migrated from Appveyor to Azure-Pipelines.

@bcampbell
Copy link
Contributor

bcampbell commented Jan 2, 2019

As much as I have issues with cmake, I feel like it's the lesser of the evils right now.
It's widely used, so is a low barrier to both users and packagers (eg the linux & bsd distros, msys2, homebrew, whatever).
As @andlabs alluded to, don't underestimate how much horror can be involved for windows users getting a working python/java/bash/gnu make/etc set up. CMake isn't immune to windows-installation-pain, but it's at least a common build system and doesn't pull in anything else.
It's got lots of warts, but assuming there aren't any showstoppers we just figure out workarounds and live with slightly icky CMakefile.txt files.
(and if there are any showstoppers for what is a pretty bog-standard library project like libui, I'd assume the cmake devs would want them fixed pretty damn quick - there must be a million projects with the same build requirements as libui).

So for me, the core switching-to-a-new-build-system question is:
Does the pain of extra dependencies (across all platforms) outweigh the pain of supporting CMake's warts?

@msink
Copy link
Contributor

msink commented Jan 3, 2019

So one more possible replacement to CMake is recent CMake - maybe 3.8 or even more recent.

@franko
Copy link

franko commented Jan 3, 2019

I suggest trying Meson by creating a Meson configuration alongside to the current one, based on cmake, one see how it works in practice.

@davidkna
Copy link

davidkna commented Jan 4, 2019

As far as meson and its dependencies on Windows go the MSI installer supposedly handles installing both python and ninja.
That doesn't help if users use pip to install it but it's something.

@andlabs
Copy link
Owner Author

andlabs commented Jan 4, 2019

My biggest worry about meson right now is that it seems like build settings and build configurations have to be hardcoded in some extra text file instead of being passed to the meson command line, and that cleaning up to do a fresh build is more than just removing a build folder. Is that true?

@msink
Copy link
Contributor

msink commented Jan 4, 2019

No - meson writes everything in build directory, same as CMake.

@franko
Copy link

franko commented Jan 4, 2019

Confirm.

Here the documention for Meson's Build Options. Every options you may set will be inside the build directory.

The Meson "configuration" is something else. Here the Meson Configuration page. Configuration can be used to generate a config.h header file, for example, starting from "config.h.in" according to variables and rules you can define in the meson build file (equivalent to CMakeLists).

@andlabs
Copy link
Owner Author

andlabs commented Jan 4, 2019

Thanks. I was referring to the former link, for the record. I was under the impression you defined the values of the configuration options for each build IN that text file, but good to see I was wrong. Still a bit concerned about predefined options... (Also not sure why that text file is needed to be separate from the main meson file...)

@msink
Copy link
Contributor

msink commented Jan 4, 2019

You can use --buildtype=plain - no extra build flags are used, even for compiler warnings, useful for distro packagers and other cases where you need to specify all arguments by yourself

@andlabs
Copy link
Owner Author

andlabs commented Jan 4, 2019

Not sure how that relates to what I said...? To be more precise, I was under the impression that you were to specify the values you WANTED to use for a specific build in the text file, not just the defaults.

Also I should be a bit more clear about my problem with predefined options, now that I skimmed through that particular page: a) whether I can use ninja with msvc, and b) (and more important) whether I can make certain options ineffective as they will not be used by libui, or force them to a specific value (or at the very least change the default value)

@msink
Copy link
Contributor

msink commented Jan 4, 2019

a) yes, --backend ninja and msvc in PATH
b) to be sure that meson will not add any default options to compiler - --buildtype=plain

@profi200
Copy link

profi200 commented Jan 8, 2019

Look, i understand you want to switch but is it worth it? This is a platform independent easy and small GUI lib and i have high hopes for it when it's ready. Qt is the only other more or less proper GUI lib but it's bloated as hell and not suitable for small projects. Shipping simple tools with near 20 MiB of bloat or even dlls is not an option. Cluttering this lib with obscure dependencies is not what i had hoped for to be honest. It's ultimately your decision but please overthink this carefully. These niche build systems are not any better than cmake.

@cody271
Copy link
Contributor

cody271 commented Jan 8, 2019

I agree with @profi200 here. CMake is by far the most popular cross platform build tool. There just isn't a strong argument to changing build tools at this time. Especially given that our use of CMake is actually quite simple compared to most other projects..

@simplexidev
Copy link
Contributor

Using CMake as you are now makes it pretty simple to figure out what is going on, with little experience with C or CMake (in comparison to a lot of other projects, as @cody271 said).

Plus, for windows developers, its a one-click install when installing Visual Studio. I'm not sure about other tools.

@bcampbell
Copy link
Contributor

Oh yes, I forgot Visual Studio was supposed to be introducing built-in support for CMake projects! https://aka.ms/cmake

@simplexidev
Copy link
Contributor

@bcampbell It's currently available (and installed by default when selecting the 'C' component) starting with VS2019 (Preview 1.x)

@andlabs
Copy link
Owner Author

andlabs commented Mar 18, 2019

Okay, I started testing to see if I could make libui into a Meson project. One hiccup I'm seeing right away: is there a way I can set c_winlibs and cpp_winlibs on a per-target basis? Should I just require them to be clear instead? Because static and shared libraries and their respective executables will have different requirements for what libraries to link against, and I don't want to be redundant here; and especially since I'll need to customize the lists anyway.

And is it possible to have a both_libraries have different dependencies, so the required resource file is only included in the shared library? If not, I'll just disallow that build mode. (Indeed, libui may not need any extra options!)

@franko
Copy link

franko commented Mar 18, 2019

In my project of providing a Meson build for the FOX library I used the following approach:

foreach lib : ['comctl32', 'wsock32', 'winspool', 'mpr', 'gdi32', 'imm32']
    fox_ext_deps += cc.find_library(lib, required : true)
endforeach

in the top-level meson file, see meson.build. The variable fox_ext_deps defines the external dependencies of the FOX library.

Then for the static library I use the following:

libfox = library('FOX-1.6', fox_src,
    include_directories : fox_include,
    dependencies : fox_deps,
    cpp_args : fox_defines,
    install : true,
)

libfox_dep = declare_dependency(
    dependencies : fox_ext_deps,
    compile_args : fox_ext_defines,
    include_directories : fox_include,
    link_with : libfox
)

see file src/meson.build. The declare_dependency here declare which are the dependencies for target that depends on the FOX library, libfox in the script.

The other veriable fox_deps is used for the dependencies needed to compile and create or link the FOX library itself.

@andlabs
Copy link
Owner Author

andlabs commented Mar 25, 2019

I tried meson over the weekend. I'm actually surprised: a lot of what I worried about were more or less moot when I actually started, and meson's default options might actually satisfy all my use cases, so I'm very likely going to be going with this. I still have some loose ends to fix, cleaning up of these files, unanswered questions, and also replacement of the CI environment before I can merge this back in, but it's something!

Feel free to look through the meson.build files early and make suggestions.

@bcampbell
Copy link
Contributor

I just did a build of your meson branch on Linux - I built libui and examples/controlgallery without a hitch. Felt very quick (I thought the build had failed at first!).
Was very easy to set up on debian - took me about 2 minutes all up, including grabbing a fresh clone of the libui repo, installing meson and figuring out how to invoke both it and ninja. I imagine it'd be a little more fiddly under windows, say.
So looks pretty promising, I think.

@franko
Copy link

franko commented Mar 26, 2019

I am very glad to see that the Meson build is already done, this is a very good surprise. I have tested on linux and it compiles faster than you can type "meson" :-)

On Windows I didn't have the opportunity to test but I will try when I have time using mingw64.

Otherwise I noticed that the examples and tester are not built by default and I was wondering they should be added.

I am also wondering if there is going to be a generated pkg-config file. Normally it can be done using pkg.generate like in the file the FOX-1.6 meson build, here the extract:

pkg.generate(libfox,
    filebase : 'fox',
    name : 'FOX',
    description : 'The FOX Toolkit',
    url : 'www.fox-toolkit.org',
)

In my experience it is nice to have a pkg-config file even on windows, when using mingw or msys2 for example.

The pkg-config files can be used with any build-system and they can even be used "manually". In addition you can look at their content and they are straightforward to understand. This is in stark contrast with the ugly cmake's FindPackage that only works with cmake and looks like voodoo. In addition they have the effect of forcing people to use only cmake and nothing else.

@andlabs
Copy link
Owner Author

andlabs commented Mar 26, 2019

The examples and tester are not supposed to be built by default. But they should be built with all, and I'm not sure why they aren't. Will have to ask about that.

pkg-config will come once I can declare libui stable enough to be versioned properly (after this alpha).

@solvingj
Copy link

Will MSVC compiler builds will be supported?

@andlabs
Copy link
Owner Author

andlabs commented Mar 26, 2019

Yes; meson supports that out of the box, and I already have it working. In fact, with the way things are set up now, Visual Studio projects might work better than the cmake-generated ones, so the people who insist on doing that may be happier, but I don't know for sure.

@franko
Copy link

franko commented Mar 27, 2019

The examples and tester are not supposed to be built by default. But they should be built with all, and I'm not sure why they aren't. Will have to ask about that.

I investigated this and I found out:

  1. calling "ninja" or "ninja all" is just the same thing
  2. the examples are not built because you are using "build_by_default: false" (the option defaults to true)

So the behavior of Meson is normal. "ninja" or "ninja all" will not build the examples and to build them you have to request each of them explicitly.

I suggest to just remove the option "build_by_default: false" for the examples.

@andlabs
Copy link
Owner Author

andlabs commented Mar 27, 2019

Ah. I was expecting ninja to build only the default targets, and ninja all to build everything. I'll see what I can do about that.

@andlabs
Copy link
Owner Author

andlabs commented Mar 29, 2019

Update: I've now removed all the CMakeLists.txt files, leaving only a small number of things not converted for various reasons. There are still a few loose ends to cover before I can consider this migration finished (and then I would need to update CI, which is another thing entirely), but so far, this might actually be it.

@franko
Copy link

franko commented Mar 29, 2019

There is a missing closing bracket in a Meson file. It is trivial to fix:

$ meson setup -Ddefault_library=static build
The Meson build system
Version: 0.50.0
Source dir: C:/dev/libui
Build dir: C:/dev/libui/build
Build type: native build
Project name: libui
Project version: undefined
Native C compiler: cc (gcc 8.3.0 "cc (Rev2, Built by MSYS2 project) 8.3.0")
Native C++ compiler: c++ (gcc 8.3.0 "c++ (Rev2, Built by MSYS2 project) 8.3.0")
Build machine cpu family: x86_64
Build machine cpu: x86_64

windows/meson.build:78:1: ERROR: Expecting rparen got rbracket.
        ]
 ^

so it is in the windows/meson.buil line 78, the closing bracket for windows.compile_resources.

@franko
Copy link

franko commented Mar 29, 2019

Once this problem is fixed, on mingw64, I get a strange compile error that doesn't seem related to Meson.

Tests on Msys2 winth MinGW64 toolchain. Commands:

meson setup -Ddefault_library=static build
meson -C build

The error I get:

../windows/colordialog.cpp:320:49: error: no matches converting function 'GetPixelFormat' to type 'GetPixelFormatF' {aka 'struct D2D1_PIXEL_FORMAT* (struct ID2D1RenderTarget::*)(struct D2D1_PIXEL_FORMAT*)'}
   gpf = (GetPixelFormatF) (&(rt->GetPixelFormat));
                                                 ^
In file included from ../windows/winapi.hpp:44,
                 from ../windows/uipriv_windows.hpp:2,
                 from ../windows/colordialog.cpp:2:
C:/msys64/mingw64/x86_64-w64-mingw32/include/d2d1.h:879:41: note: candidates are: 'D2D1_PIXEL_FORMAT ID2D1RenderTarget::GetPixelFormat() const'
     D2D1_PIXEL_FORMAT STDMETHODCALLTYPE GetPixelFormat() const {
                                         ^~~~~~~~~~~~~~
C:/msys64/mingw64/x86_64-w64-mingw32/include/d2d1.h:878:50: note:                 'virtual D2D1_PIXEL_FORMAT* ID2D1RenderTarget::GetPixelFormat(D2D1_PIXEL_FORMAT*) const'
     virtual D2D1_PIXEL_FORMAT* STDMETHODCALLTYPE GetPixelFormat(D2D1_PIXEL_FORMAT*) const = 0;
                                                  ^~~~~~~~~~~~~~

it could be related to a recent update I made with msys2.

@andlabs
Copy link
Owner Author

andlabs commented Mar 29, 2019

Yes, that's a different problem, with a different bug entirely. I already know how to fix it (change the two typedefs to add const at the end), but I need to test the fix on MSVC as well; I'll do that on master instead of this branch.

@andlabs
Copy link
Owner Author

andlabs commented Apr 8, 2019

I fixed the problem in this branch after all.

@andlabs
Copy link
Owner Author

andlabs commented Apr 8, 2019

I'll test binaries separately.

@andlabs andlabs closed this as completed in 88a3267 Apr 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants