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
Requirements, indicating how hard or soft they are:
.exe.manifest files impossible; see this)mkdir build; cd build; tool option=setting option2=setting2 and must be as easy to clean up as rm -rf buildSuggested by others for replacement:
Other possibilities, in order of decreasing likelihood:
Suggestions from below:
Non-starters:
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.
What about buck build system? https://buckbuild.com/
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.
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.
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.
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?
So one more possible replacement to CMake is recent CMake - maybe 3.8 or even more recent.
I suggest trying Meson by creating a Meson configuration alongside to the current one, based on cmake, one see how it works in practice.
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.
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?
No - meson writes everything in build directory, same as CMake.
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).
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...)
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
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)
a) yes, --backend ninja and msvc in PATH
b) to be sure that meson will not add any default options to compiler - --buildtype=plain
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.
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..
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.
Oh yes, I forgot Visual Studio was supposed to be introducing built-in support for CMake projects! https://aka.ms/cmake
@bcampbell It's currently available (and installed by default when selecting the 'C' component) starting with VS2019 (Preview 1.x)
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!)
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.
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.
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.
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.
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).
Will MSVC compiler builds will be supported?
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.
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:
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.
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.
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.
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.
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.
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.
I fixed the problem in this branch after all.
I'll test binaries separately.
Most helpful comment
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.txtfiles.(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?