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

Meson build #22

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open

Meson build #22

wants to merge 25 commits into from

Conversation

whs
Copy link

@whs whs commented Sep 4, 2021

Per my offer on Mastodon, here's a Meson build implementation for libdatrie. Hopefully closes #13, as it should be less painful than autotools but it's not CMake.

What works:

  • Building on Arch Linux (I have system-installed datrie, so it might not be a good test...)
  • Building on Mac (This one doesn't have system datrie, so it should ensure that a clean system are able to build)
  • Building trietool
  • Running test (meson even comes with junit-style XML and this cute test runner which phase of the moon is the running indicator)

image

Needs to know for maintainer:

  • Version needs to be bumped in /meson.build line 1. This version is used as .so suffix.
  • There is no support for -liconv detection. Instead, it would try building without flags, and then use meson dependency resolution to find iconv. Notably, on Mac it use FindIconv from CMake, so it is a compile time dependency on the Mac.
    • I think on Linux we could simplify the code by also using FindIconv, removing any home grown checks. This would make CMake compile time dependency on all platforms.
  • The line
    echo '{global:hello; local:*;};' > conftest.ver
    has been extracted to a file, as Meson don't like generating things. Alternatively I could just test it with the real file (which was my first approach).
  • pkg-config is generated by meson instead of using the one we already ship
  • dist generated by meson works (including autotools build) but the version number is incorrect, as the project has two different version scheme. Fixing this would requires the maintainer to update the version number in meson.build (which is probably what meson intended) instead of using shell commands.

What needs to be tested:

  • Building on other BSDs and other unixes (hopefully we would just ship dual meson-autoconf build and wait for feedback)
  • I'm not sure if linker versioning & exports are correct, as meson doesn't have the same feature as autoconf and I don't know that much about linker

@whs
Copy link
Author

whs commented Sep 4, 2021

[8/43] Compiling C object tests/test_walk.p/test_walk.c.o
../tests/test_walk.c:78:26: warning: format specifies type 'wint_t' (aka 'int') but the argument has type 'AlphaChar' (aka 'unsigned int') [-Wformat]
        printf ("'%lc'", walkables[i]);
                  ~~~    ^~~~~~~~~~~~
                  %c

Got this on Mac

CPU: quad-core 64-bit kabylake
Clang: 12.0.5 build 1205
Git: 2.32.0 => /usr/local/bin/git
Curl: 7.64.1 => /usr/bin/curl
macOS: 11.5.2-x86_64
CLT: 12.5.1.0.1.1623191612
Xcode: 12.5.1

All tests were passing though

Here's the meson-generated pkgconfig

prefix=/Users/user/libdatrie/builddir/install
libdir=${prefix}/lib
includedir=${prefix}/include

Name: datrie
Description: Double-array trie library
URL: https://github.com/tlwg/libdatrie
Version: 0.2.13-14-g3b57a6c
Libs: -L${libdir} -ldatrie
Libs.private: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/usr/lib/libiconv.tbd
Cflags: -I${includedir}

@pepa65
Copy link

pepa65 commented Sep 4, 2021

Doesn't sound like an improvement over the old system (so far at least)... I know 1 person complained, but for everyone else autotools seems to work OK.

@whs whs marked this pull request as ready for review September 12, 2021 04:37
@whs whs changed the title WIP: Meson build Meson build Sep 12, 2021
Copy link

@eli-schwartz eli-schwartz left a comment

Choose a reason for hiding this comment

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

Hi, nice to see you considering meson. Some suggestions for potential optimizations:

meson.build Outdated

# Detect for iconv
compiler_has_iconv = compiler.has_function('iconv_open')
iconv_pkgconfig = get_option('iconv_pkgconfig')

Choose a reason for hiding this comment

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

Hmm??? Which system has a pkg-config file for iconv?

For the record, as I've just added mesonbuild/meson#9205 to meson, this should work on (unreleased) meson 0.60 out of the box, but it will do the has_function check for you followed by looking for compiler.find_library('iconv')

So this entire section could be reduced to one line, but you'll need to target meson >= 0.60

Copy link
Author

Choose a reason for hiding this comment

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

I think the flag is misnamed, it's more like use Meson's resolver to find iconv (which is required on a Mac - FindIconv is needed)

I think it should be harmless to remove the flag entirely and always use the auto path here?

Choose a reason for hiding this comment

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

Does FindIconv do anything above and beyond detecting the existence of a find_library('iconv')?

Because having this detection not work on systems without cmake installed, is unfortunate.

Copy link
Author

@whs whs Sep 13, 2021

Choose a reason for hiding this comment

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

Since iconv doesn't come with pkg-config, and we only check for builtin iconv_open here, it doesn't work on a Mac which needs -liconv to link. FindIconv does give us the flags we need, so it essentially serve as the pkg-config file

Choose a reason for hiding this comment

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

Right, but compiler.find_library('iconv') also gives you -liconv without using cmake to look it up.

Copy link
Author

Choose a reason for hiding this comment

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

Turns out mingw-w64 does ship iconv. I guess I have to add back dependency support.

Choose a reason for hiding this comment

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

That pkg-config file appears to come from the msys2 packaging, not upstream iconv. And it returns the same information that find_library() returns.

I would not bother using it since it's not an official pkg-config file.

meson.build Outdated Show resolved Hide resolved
meson.build Outdated Show resolved Hide resolved
meson.build Outdated Show resolved Hide resolved
@whs
Copy link
Author

whs commented Sep 13, 2021

Updated

  • Removed iconv_pkgconfig and add check with compiler.find_library
  • Removed ld_no_undefined

Test build was done in Arch Linux & Mac (without CMake installed)

link_depends : link_depends,
version : meson.project_version(),
include_directories : configuration_inc,
vs_module_defs : 'libdatrie.def',
Copy link
Author

Choose a reason for hiding this comment

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

This break Windows gcc

Choose a reason for hiding this comment

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

The vs module defs file? Why?

Copy link
Author

Choose a reason for hiding this comment

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

I thought it would supply the .def file generated in the block for msvc above (I think I forgot to change this line to reference the generated file). However, the original def file here got passed to gcc which breaks.

I'm not sure why - I'm not exactly familiar with msvc/mingw (and it seems this project doesn't run on Windows either) I'm guessing that both compilers use the same linker def format on Windows? Maybe if I supply the generated file to gcc it might work.

Choose a reason for hiding this comment

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

Ah, right, you'll need the link_def variable reference which contains a custom_target output.

I'm not actually sure I understand the custom_target? Is it just prepending a single constant line? Why isn't this changed in the source file so that you don't need to generate anything?

Also yes, the GNU compiler implementation in meson passes the defs file to the linker as this is valid there.

Copy link
Author

Choose a reason for hiding this comment

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

Yes it is passing a single line. I'm not sure how the original file is used, but it was used as-is in autotools (and I don't know which platform it was for - on Linux it use .map) so I didn't want to touch it. On Windows you need a section marker so I took inspiration from #15 to add it during build time.

@Kreijstal
Copy link

Thank you this solved my problem, with #29

@thep
Copy link
Contributor

thep commented May 17, 2024

First of all, thank you very much for your work, and sorry for a very slow response. It took me a long while to find some time to study meson so I can understand your proposal.

Here are what I noticed:

  • Warnings from meson:
WARNING: Project specifies a minimum meson_version '>=0.53.0' but uses features which were added in newer versions:
 * 0.55.0: {'Passing executable/found program object to script parameter of add_dist_script', 'Passing executable/found program object to script parameter of add_install_script'}
NOTICE: Future-deprecated features used:
 * 0.56.0: {'meson.build_root', 'meson.source_root'}
  • Library ABI version is taken from the hard-coded project version 1.4.0, which is inappropriate, as "meson dist" produces 1.4.0 tarball, while the actual version is still 0.2.13. The correct numbers should be this way:
    • Project version should be taken from the VERSION file generated by the build-aux/git-version-gen script,
    • library() version should be calculated from LT_CURRENT, LT_REVISION and LT_AGE defined in configure.ac like this:
soversion = LT_CURRENT - LT_AGE
libversion = '@0@.@1@.@2@'.format(soversion, LT_AGE, LT_REVISION)
  • Tarball generated by "meson dist" includes excessive files like .cvsignore, .gitignore, autogen.sh, the whole autom4te.cache/ directory, nsis/ directory.

When the meson build is ready, I think we can move away from autotools and maintain only one build system in the end.

@eli-schwartz
Copy link

  • Tarball generated by "meson dist" includes excessive files like .cvsignore, .gitignore, autogen.sh, the whole autom4te.cache/ directory, nsis/ directory.

It includes the output of running autogen.sh which is arguably important to ensure that meson dist is a suitable replacement for autotools make dist during a transition phase from one to the other.

Arguably .cvsignore could just be deleted from the repo ;) and the gitignore file can be excluded using gitattributes export-ignore.

@thep
Copy link
Contributor

thep commented May 17, 2024

  • Tarball generated by "meson dist" includes excessive files like .cvsignore, .gitignore, autogen.sh, the whole autom4te.cache/ directory, nsis/ directory.

It includes the output of running autogen.sh which is arguably important to ensure that meson dist is a suitable replacement for autotools make dist during a transition phase from one to the other.

autogen.sh has never been distributed with the tarball so far. It's intended for use in the repo only. Surely the cache dir autom4te.cache/ is not for distribution. For nsis/, it's experimental Windows installer, which is not ready for distribution yet.

The decent outputs of autogen.sh not mentioned above, such as the configure script, Makefile.in, config.guess, config.sub, the m4/ directory, etc, are not part of the problem here.

Arguably .cvsignore could just be deleted from the repo ;) and the gitignore file can be excluded using gitattributes export-ignore.

No doubt for this.

@whs whs mentioned this pull request May 19, 2024
@whs
Copy link
Author

whs commented May 19, 2024

So what's left for this PR to be merged? I might be able to work on it right away but would be great if I could have a list. From what I understand:

  1. Bump Meson version. The current version was chosen because it was the oldest version available in major Linux distros at the time, but it's too old to use even back then.
    • Survey for a new Meson version to use
    • Fix any deprecated features
  2. Figure out how to separate library version and so version.
    • I think Meson is against running script as part of the process formerly done in configure phase, so running git-version-gen might not be possible unless Meson actually provide that exact functionality in the stdlib
  3. Remove .cvsignore, add .gitignore, autogen.sh, autom4te.cache, nsis to .gitattribute

I don't know about the current state of Windows builds so I'm not sure if the discussion with @eli-schwartz above is still valid or not. Personally I don't want to hand test all the OSes again (I don't have access to any Mac now) so I'd prefer those test to be done by GitHub Actions. I could contribute one later if this get merged.

@eli-schwartz
Copy link

eli-schwartz commented May 19, 2024

I think Meson is against running script as part of the process formerly done in configure phase, so running git-version-gen might not be possible unless Meson actually provide that exact functionality in the stdlib

There's nothing wrong with doing this.

project(...,
    version: run_command('./git-version-gen', check: true).stdout().strip()

Note that it will only be run on configure, so if the output changes after a git pull a new configure won't be done and the version number becomes outdated.

vcs_tag() can be used to generate a version.h file as a build edge (produced every time you run ninja) if that's an unacceptable shortcoming.

But it depends on whether the project version is used for anything at build time other than e.g. the configure summary text, and whether you are actually worried if it gets out of date. Some people are, some people aren't.

@whs
Copy link
Author

whs commented May 22, 2024

Updated

  1. Project version now use git-version-gen and so version is now computed in meson. This means it has to be updated in both configure.ac and meson.build, but once autotools is removed it will only be in meson.
  2. Dist file should be equal now. The m4 build cache was in there because I run autogen.sh during dist and unlike autotools dist it wasn't cleaned automatically.
  3. There was a bug during dist that it do not honor DESTDIR. This is now fixed
  4. Now that Meson has new iconv detection, remove special iconv logic. The other two detection I'm not exactly sure if required so I still leave it in.
  5. Minimum Meson version is now 1.0. This should be minimum version for current version of all major LTS distros except RHEL9 derivatives.

I also tested the build with muon and the test passes. It doesn't seems to implement the same iconv check as meson, but at least on Linux-glibc one doesn't need special flags for iconv anyway.

@pepa65
Copy link

pepa65 commented May 22, 2024

I am on the latest Linux Mint, it has Meson 0.61.2... But soon I hope there will be a new release.

@whs
Copy link
Author

whs commented May 27, 2024

I'm testing the build on Windows and the code build just fine in both MSVC project build, ninja build and MINGW64. I've also fixed building with Clang that comes with Visual Studio. However, some test fails for all variants.

If someone is trying to build this, install Git and Visual Studio Community 2022 with Desktop development with C++ workload. You'll need to run Meson in Git bash since we use sh to compute the version number, but the actual building should be done in the x64 Native Tools command prompt. For Clang it can be installed in Visual Studio as well. Run export CC=clang-cl and export CXX=clang-cl before running meson in Git bash.

On investigation of the MSVC version, It seems that *((AlphaChar*)L"ab") is converted as 6422625 (0110 0010 0000 0000 0110 0001 = A 0000 0000 B). Not sure why this is the case as the code expects the pointer resolution to returns 0110 0010. Perhaps the integer sizes are different? I don't write C code often and certainly not on Windows so someone else might have to fix these.

man/meson.build Outdated Show resolved Hide resolved
meson.build Outdated Show resolved Hide resolved
tools/meson.build Outdated Show resolved Hide resolved
@whs
Copy link
Author

whs commented Aug 12, 2024

Updated a bit to fix bad merge, and updated subproject usage to automatically override parent project dependency & trietool for better subproject UX.

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

Successfully merging this pull request may close these issues.

Replace autotools with CMake
5 participants