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

Support building for Windows with clang-cl #541

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

fanc999-1
Copy link

Hi,

This attempts to add build support for Windows using clang-cl (the flavor of clang that attempts to mimick Visual Studio and uses the Microsoft SDKs, meaning _MSC_VER will also be defined), so that the build libraries and headers can also be better consumed by items built using Visual Studio. This is done to restore support to build libadwaita against the Microsoft tools/SDK.

This mainly consists of:

  • Making the code compile with the Windows SDK by only including headers when they are really available.
  • Using compiler directives to export symbols from shared builds via defining macros. Also, for the private symbols, define macros suitable for clang-cl for visibility. clang-cl (and Visual Studio) build DLLs with hidden visibility by default.
  • Improve dep search using CMake names where needed also, as CMake build files for Visual Studio builds often do not produce pkg-config files for us. Also avoid hard-coding paths to find the libstemmer/snowball headers. Also do not enable systemd on Windows, since it is (and is unlikely ever) not available for Windows at all

With blessings, thank you!

@ximion
Copy link
Owner

ximion commented Oct 24, 2023

Using compiler directives to export symbols from shared builds via defining macros.

Can this be done differently? I really don't like this, and it adds a ton of unnecessary noise to the code (it also doesn't look like other projects like GLib need this?).

The other changes look okay from a quick glance, thank you a lot for this work! Having CI for this will be very helpful! :-)

@ximion
Copy link
Owner

ximion commented Oct 25, 2023

To elaborate on the exported symbols: AppStream exports everything on Linux/FreeBSD/MacOS that is not wrapped by AS_BEGIN_PRIVATE_DECLS/AS_END_PRIVATE_DECLS which simply switches the default symbol visibility to "hidden". Stuff in *-private.h headers is generally not exported. This setting can be overridden for individual symbols via AS_INTERNAL_VISIBLE. Those are exported, but are not part of the public API so must not be used outside of AppStream (and will not be available in public headers).

So all that would be needed is make clang export everything by default and adjust the macros to negate the export option for subsequent declarations with whatever commands Microsoft has set for that. That must be possible somehow, I'd imagine.

@fanc999-1
Copy link
Author

fanc999-1 commented Oct 25, 2023

Using compiler directives to export symbols from shared builds via defining macros.

Can this be done differently? I really don't like this, and it adds a ton of unnecessary noise to the code (it also doesn't look like other projects like GLib need this?).

The other changes look okay from a quick glance, thank you a lot for this work! Having CI for this will be very helpful! :-)

I'll try to see whether there are any better ways for this--GLib/Pango/GTK do have something like this though, however, via the GLIB_AVAILABLE* macros that decorate symbols, in GLib for instance, and on Visual Studio and clang-cl they will be defined as __decspec(dllexport) during the build.


It does seem the other way is to try to generate a .def file using dumpbin /exports dumpbin /symbols, but the price is likely that those in the visibility hidden section gets exported as well, so this is what I have here, along with an intermediate static lib that is built so that we can use call dumpbin easier.


Thanks for the suggestions though.

@fanc999-1 fanc999-1 force-pushed the clang-cl branch 6 times, most recently from 69f1f1c to bf7d79a Compare October 31, 2023 06:00
The Windows build systems of some dependencies (i.e. CMake) may not generate
pkg-config files for us, but almost certainly generate CMake config files, so
look for them as well, as their names differ from the .pc files.
Don't try to add '/usr/include' to the include directories as it may not exist
on Windows, without checking for its presence.  Likewise, check for
'libstemmer/libstemmer.h' only if '/usr/include' is found.

Also, streamline finding the libstemmer libraries so that we look for
libstemmer.h at the same time as looking for the stemmer library, to ensure
that things are properly set up.
... and use it as applicable, as we are going to disable deps and features that
are clearly not applicable for Windows.
systemd is not meant for Windows, so no point enabling it on Windows
The code using things from this header only applies to Linux.
clang-cl uses the headers from the Visual Studio and Windows SDK installation,
so make sure that we are including the right headers on Windows for the things
we are using in the code.  In particular, unistd.h is a wrapper header on MinGW
builds which include the various Windows system headers for the things that are
actually done.

Also, for calling umask(), just use S_IREAD | S_IWRITE for the default
permissions on Windows.
This is modelled like what is done in gtksourceview, so that we can use
extract_objects() on the intermediate target so that we can use dumpbin
to extract the symbols that is built in the appstream DLL.

We might be able to make tests and utilities depend on this intermediate
target, if needed, instead of exporting a bunch of private symbols in the
shared library.
This way, we can export all the non-static symbols from the appstream DLL that
we are trying to build, without touching the headers too much, by using the
dumpbin tool that comes with every installation of Visual Studio, which clang-cl
uses.

Sadly, this approach does not allow us to effectively filter out those we mark
with the GCC hidden visibility atribute, so this is the best we can do.
It's not used there, and it's really a wrapper header in MinGW that include
various Windows system headers and define things to ease porting POSIX items
to Windows.
Like previous commits, avoid including unistd.h on Windows, and just bail out
trying to run package managers or flatpak as they are more or less concepts
that are foreign to Windows, at least for now.
On clang-cl (i.e. Visual Studio-like meaning _MSC_VER is defined) builds,
symbols in shared builds have visibility to be hidden by default, and
decorating symbols with GCC's default visibility is not enough to export the
symbol.

Consequently, use the macros in as-desktop-entry.h so that we don't fall into
the situation where clang-cl complains as we are attempting to do a
__declspec(dllexport) in a hidden visibility section.
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.

None yet

2 participants