-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Build with CMake #4455
Build with CMake #4455
Conversation
Oh my gosh, thank you! I've locally been building fish with meson for its ninja backend, but that has the extremely unfortunate side effect of introducing python as a build requirement (the meson team feels that's OK, though I disagreed). cmake or meson piping to ninja would both generate far smarter build files that do not need to rebuild as much or as often when jumping between revisions to test when/where something broke. With regards to your point:
I would argue that this is a dealbreaker, and we shouldn't release without end users being able to |
I wonder how other OSS projects handle that. It looks like libpng and pcre2 both manually maintain CMake and autotools systems, which seems nuts. bro has ./configure and Makefile wrappers that call out to CMake, which seems OK. It might be worth asking on StackOverflow or CMake mailing list. Edit: also found https://github.com/nemequ/configure-cmake |
Super cool! |
configure-cmake looks interesting, nice find. I was actually thinking of a configure script that would take take a cmake-generated makefile and plug in neovim wraps cmake in a Makefile that shells out to cmake and ninja, no (When I was deciding between meson, cmake, and other "modern" build systems for $work I came across tup which is downright awesome (and generates dependency-free build scripts for distribution tarballs) and written by folk that obviously have their head on straight, but it has a dev (not build) dependency on fuse (which is how it operates; inspecting which files are opened during build and automatically configuring them as dependencies), but the fuse dependency is a huge non-starter and makes Windows support (even via WSL) out of the question.) |
Hehe... so we've had at least two people trying out meson. I did as well, and here's what I wrote up then:
So unlike @mqudsi, I never really had an issue with the python dependency, though my concern is mostly linux systems, and those tend to have python anyway. What I did have an issue with is that meson is still so new that it's adding functionality left and right, so it's kinda hard to use it in such a way that it still works on old OSen - if they have it at all. So, as you might see, cmake in this implementation solves all of those issues - it already has the doc stuff (that I never really attempted since I gave up after figuring out that it was a non-starter for Debian), the version generation works, cmake has "GLOB" to avoid specifying every .po file and .fish script. It can also still use ninja, which manages to make the build quite a bit faster (though cmake's makefiles are apparently bad, since a cmake-with-make build takes 50% longer on my system than with our autoconf one). So, while I like meson's syntax a bit more than cmake (and I dislike having to explicitly pick ninja), cmake solves some real problems we'd have with it. It's also just simply more well-known than meson. (Thwough of course it's possible that @mqudsi's meson work is better than mine, since I am not well-versed in build systems) So, I am apparently not alone in not loving autostuff/make. IMHO, the main advantage it has is that it's ubiquitous. However, cmake is also available on every linux distribution, and has been for quite a while. It's available on windows and I'd imagine the BSDs. I don't think availability is going to be an issue. There is one thing that I dislike in pretty much anything that isn't autotools, and that's configuring directories. I'm currently rewriting my PKGBUILD (the thing that gives me nice archlinux packages to install) to use cmake if available, and I find it really hard to pass the right things. I.e.
is noticeably uglier than and doesn't work as a replacement for
|
For some reason, the |
Surprised that the CMake build is linking libform, which the autotools build does not. $ otool -l fish
...
Load command 13
cmd LC_LOAD_DYLIB
cmdsize 56
name /usr/lib/libform.5.4.dylib (offset 24)
time stamp 2 Wed Dec 31 16:00:02 1969
current version 5.4.0
compatibility version 5.4.0
... |
@floam the CMake build by default is -O0, the autotools build is -O2. Can you repeat your experiment except run
|
Yeah, it was just the optimization level. Release build is way smaller. |
Do we want to set the default level via CMake to the same we currently use? |
@zanchey what do you think about the switch to CMake? If we have consensus, we should probably merge these changes to a cmake branch upstream so we can make PRs against it. |
@mqudsi IMO the CMake default of -O0 is better for day to day development: faster builds and easier debugging. I'd like to keep it. If we decide to go with this I don't think we need an upstream branch, we can just merge to master. This doesn't break the autotools build. |
SGTM! |
@ridiculousfish does the cmake build also depend on pkg-config? I keep forgetting to double check and then update the readme to note that building fish via autotools currently indirectly depends on pkg-config. |
We depend on pkg-config? I don't have it and have never had trouble with anything. |
I recall being unable to build on solaris without installing it. But like I said, I'd have to double-check. That said, I'm surprised you don't have it installed; it usually ends up being installed regardless of the package manager you use on most modern *nix systems. |
I use MacOS, FWIW. |
Hmmm, reviewing my logs it seems that I did have to install pkg-config but removing it now allows fish to build. Perhaps I need it to build a dependency or something... no matter. |
0ad7d75
to
4d9397b
Compare
Looking over FindCurses, it looks like --- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -90,7 +90,7 @@ ENDFUNCTION(FISH_LINK_DEPS)
ADD_LIBRARY(fishlib STATIC ${FISH_SRCS})
TARGET_SOURCES(fishlib PRIVATE ${FISH_HEADERS})
TARGET_LINK_LIBRARIES(fishlib
- ${CURSES_LIBRARIES} Threads::Threads ${CMAKE_DL_LIBS}
+ ${CURSES_LIBRARY} ${CURSES_EXTRA_LIBRARY} Threads::Threads ${CMAKE_DL_LIBS}
${PCRE2_LIB} muparser)
# builtin_math.cpp needs to see muParser's built header. |
This adds a basic CMakeLists.txt. It also adds a ConfigureChecks.cmake and config_cmake.h.in that produces a config.h.
This adds files MuParser.cmake and PCRE2.cmake. PCRE2 is built using its own CMake path, while MuParser uses ExternalProject.
This adds a basic Tests.cmake that can build and run fish_tests. It also adds a 'test' target.
This adds CMake targets for fish_indent and fish_key_reader.
This adds a new script build_tools/build_lexicon_filter.sh that builds the lexicon filter. It is factored out from the Makefile, and both the Makefile and CMake build invoke it.
As part of factoring out the documentation building parts of the fish build, add a new file build_commands_hdr.sh that builds the commands.hdr file. Invoke it from both the Makefile and CMake build.
As part of factoring out the documentation building parts of the fish build, add a new file build_index_hdr.sh that builds the index.hdr file. Invoke it from both the Makefile and CMake build.
As part of factoring out the documentation building parts of the fish build, add a new file build_index_hdr.sh that builds the index.hdr file. Invoke it from both the Makefile and CMake build.
As part of factoring out the documentation building parts of the fish build, add a new file build_user_doc.sh that builds the user_doc directory. Invoke it from both the Makefile and CMake build.
This adds support for creating the FISH-BUILD-VERSION-FILE in the CMake build. A FISH-BUILD-VERSION-FILE is created in the CMake directory and only updated when necessary.
This adds a file Install.cmake for installing fish. It is quite incomplete; in particular it does not support building the docs.
This adds a new library fishlib, which the CMake build builds. This library is linked by the tests, fish, and fish_indent, so that object files do not have to be built separately for each of them.
This adds support in Tests.cmake for running the script and other "high level" tests, in addition to the unit tests fish_tests.
This adds intelligent groups and hides unused files when generating IDE projects (Xcode, CLion, etc) in the CMake build.
This links against CMAKE_DL_LIBS, reflecting the recent change 73f2992.
Switch to ${CURSES_LIBRARY} and ${CURSES_EXTRA_LIBRARY} instead of ${CURSES_LIBRARIES} to reduce the linked libraries in the CMake build.
b8a425b
to
2ca7b88
Compare
One problem I've run into is that the CMakeFiles directory is used by CMake for the actual build process, so in-tree builds (i.e.
|
I didn't know in-tree builds were even a possibility outside of a dedicated ./build directory, but if it's easy to fix let's do it! |
I have a patch series in the works that fixes that, among other things. |
See #4535 for further work. Still remaining:
|
AFAICT the only thing still requiring autotools is the build_tarball script |
TLDR: let's build fish with CMake and eventually replace autotools, so we can drop a ton of cruft. This PR has enough for day-to-day development with CMake. I'm looking forwards to feedback and discussion.
What is CMake?
CMake is a meta-build system. At a high-level it plays the same role as ./configure by generating a Makefile, but it can also output other builds (Ninja, CLion, XCode, CodeBlocks VS, and more).
CMake is mature and battle-tested. It's used by major OS projects like LLVM, KDE, MySQL. It has great docs and is easy to find help on StackOverflow, etc.
KDE switched to CMake, here's their story.
Probably you already know CMake and hopefully don't need to be sold on it. If not there's info on CMake advantages at the bottom.
What does this PR include?
This PR:
What's missing:
Try it!
Easy peasy:
git checkout
this PR.mkdir /tmp/fish-build ; cd /tmp/fish-build
cmake /path/to/fish-shell
make test
mkdir /tmp/fish-install ; env DESTDIR=/tmp/fish-install make install
make VERBOSE=1
for a verbose build.Advanced command line users will like Ninja:
cmake -G Ninja /path/to/fish-shell; and ninja
Or if you want Xcode:
cmake -G Xcode /path/to/fish-shell
What happens if we merge this?
Here's a sketch of how this could go:
How does the CMake build handle:
PCRE2: This PR uses the system PCRE2 if one is installed. If not, it builds the bundled PCRE2 via CMake (which PCRE2 conveniently supports). Once we remove support for autotools we can stop bundling pcre2 and use the CMake package management.
muParser: This builds muParser as an ExternalProject using the muParser autotools build. The path forward here is to fork muParser, and add our own CMake build system.
Docs: The docs are by far the most complicated part of fish build. The autotools path uses a bunch of sed commands and relies on many temporary files. This PR factors those commands into separate shell scripts under build_tools, which both the Makefile and CMake invoke.
This is admittedly gross, but the docs build was already gross. It should be factored into a monolithic script that builds everything, instead of granular individual targets.
What does CMake bring to the table?
Mature, battle-tested, widely available
This is the main advantage that CMake has over gyp, boost.build, scons, etc. No build system is as ubiquitous as autotools, but CMake is number two.
Much simpler builds
autotools builds are famously difficult to maintain: arcane m4 syntax, workarounds for ancient systems, layers upon layers. CMake's syntax is a little weird, but simple and regular.
Nested projects are very common and easy with CMake. It is very simple to build PCRE2 as a nested project using PCRE2's CMake path. No more "recursive Make considered harmful."
CMake also knows about development artifacts such as header files and libraries. autotools must be manually taught header dependencies ("make depend"), filename extensions (.so vs .dylib), so on.
Actual package management
CMake has built in support for external dependencies. It knows how to look for them locally, fetch them via git, etc. PCRE2 would have been much simpler to add to fish if we were using CMake.
Replaces XCode project
Unlike Make, CMake knows about macOS-isms like bundles and deployment targets. We can support macOS's needs without maintaining the separate XCode project and osx/ contents.
CMake can also generate CLion or VS projects, so we can support a lot more IDEs.
Out-of-source builds
CMake builds in a different directory from the source code. This takes a little bit of getting used to but is actually great. Your source directory stays clean.
make distclean
becomesrm -Rf *
. Multiple builds (debug vs release) are trivial.This is possible in princple with autotools, but takes a lot of work.
Disadvantages of CMake
./configure ; make ; make install
, unless we provide a wrapper.active_test_goals
hack from make, which serializes tests but only those that are to be run. However CMake has good support for invoking external scripts, so it ought to be flexible enough.