NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.23k stars 14.22k forks source link

CMake can't find gdkconfig.h and glibconfig.h #71091

Open vvs- opened 5 years ago

vvs- commented 5 years ago

Describe the bug If you try to build any software that uses CMake and GTK2 you'll notice that CMake can't find all the required components. In particular it'll complain about GTK2_GDKCONFIG_INCLUDE_DIR and GTK2_GLIBCONFIG_INCLUDE_DIR not found. This bug is presently circumvented in Nixpkgs by using Nix expressions to substitute actual paths to CMake before configuring phase so it won't need to search for them.

While this works for Nixpkgs it makes it extremely difficult for newbies to compile such software from sources. Using just nix-shell won't suffice anymore. I believe that fixing CMake FindGTK2 module would make more sense.

To Reproduce Steps to reproduce the behavior:

  1. Create a test CMakeLists.txt with just one line: find_package(GTK2)
  2. Run nix-shell -p cmake pkgconfig gtk2
  3. Run cmake .

Expected behavior It should succeed without complaining about files not found.

Metadata

 - system: `"i686-linux"`
 - host os: `Linux 5.2.17, NixOS, 19.03.173553.6420e2649fa (Koi)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.2.2`
 - channels(root): `"nixos-19.03.173553.6420e2649fa"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
jtojnar commented 5 years ago

Unfortunately, CMake modules are often written in the least portable way possible, usually hard-coding paths like this:

https://github.com/Kitware/CMake/blob/25eef45f16aa2046071d847d93314f3b843c870d/Modules/FindGTK2.cmake#L292-L317

IMHO, the best approach would be rewriting the module to find the appropriate paths using pkg-config, which would probably also be upstreamable. Maybe open an issue upstream.

vvs- commented 5 years ago

Even worse. There exists a habit to distribute package's own CMake modules within the sources. This is particularly popular for modules that don't (yet) exist in CMake. BTW, the same practice exists for GNU autotools as well.

I wasn't able to find anything that would suggest how to solve this particular problem in NixOS. I've found parts of the solution throughout Nixpkgs expressions and manuals. The purpose of this issue is to discuss best practices and at least document it.

flokli commented 5 years ago

I'm not sure if there's anything actionable in this issue itself, except of moving upstreams more to using pkg-config.

vvs- commented 5 years ago

Ok. But what others should do when confronted by this problem? Every man for himself?

Here is what I've found. Create default.nix expression with the following contents:

with import <nixpkgs> { };

stdenv.mkDerivation {
        name = "project";
        buildInputs = [ cmake gtk2 glib ];
        cmakeFlags = [
                "-DGTK2_GDKCONFIG_INCLUDE_DIR=${gtk2.out}/lib/gtk-2.0/include"
                "-DGTK2_GLIBCONFIG_INCLUDE_DIR=${glib.out}/lib/glib-2.0/include"
        ];
}

Add other required inputs and CMake flags. Put it in the same folder where top CMakeLists.txt resides. Run nix-shell and inside its prompt cmakeConfigurePhase. After that everything should work as expected.

For GTK3 change default.nix to the following contents:

with import <nixpkgs> { };

stdenv.mkDerivation {
        name = "project";
        buildInputs = [ cmake pkgconfig gtk3 glib pcre xorg.libpthreadstubs xorg.libXdmcp libuuid libselinux libsepol libxkbcommon epoxy at_spi2_core dbus ];
}
doronbehar commented 5 years ago

I think upstream should be patched. However, there seems also the env path $GTKMM_BASE_PATH Which maybe gtk2 can add to it's setup hook?

flokli commented 5 years ago

I'm not sure if I understand the problem.

If you add gtk2 to buildInputs, and also added pkgconfig to nativeBuildInputs, the tooling will add the directory of .pc files from the corresponding dev output to PKG_CONFIG_PATH - so pkgconfig will be able to provide these locations if the build system of the package you're building asks it.

This is also (somewhat) documented in the nixpkgs manual and NixOS wiki.

If the buildsystem doesn't use pkgconfig, but hardcodes this to some FHS paths, or requires you to set other variables, there's not much nix can do, how should it know how to configure the build system?

jtojnar commented 5 years ago

@flokli CMake package contains FindGTK2 module with hardcoded paths and fixing it would also fix packages depending on that module. I am not sure where we would find a person to patch that module though. Especially since only some fringe ancient projects will benefit from the fix.

vvs- commented 5 years ago

Not so ancient as you might think. Here is an IF authoring system released in October (!) which by default uses GTK2. I've encountered enough of such things. Sure, they are not as widespread as Firefox, but which programming languages are (except JS)?

BTW, search for GTK2_GDKCONFIG_INCLUDE_DIR in Nixpkgs and there are too much of it for my tastes.

flokli commented 5 years ago

@vvs- fixing FindGTK2 in cmake would surely remove a lot of these usages.

I quickly skimmed cmake, seems these hardcoded paths are in Modules/FindGTK2.cmake. We can't hardcode gtk paths in there, as this would pull in a runtime dependency on gtk.

What we could do, would be replacing these calls by some find_package(PkgConfig REQUIRED) and pkg_check_modules(…) calls - but as @jtojnar mentioned, it probably isn't that pleasant to work through this…

stale[bot] commented 4 years ago

Thank you for your contributions. This has been automatically marked as stale because it has had no activity for 180 days. If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity. Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse. 3. Ask on the #nixos channel on irc.freenode.net.
vvs- commented 4 years ago

I'm not sure if this ever will be fixed, given priority for "latest and greatest", but let's our hope to extend for another few months at least.

jtojnar commented 4 years ago

IIRC, there were some upstream changes in FindGTK2 recently does it still happen?

vvs- commented 4 years ago

Still happens with nixos-unstable.

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info

flokli commented 3 years ago

This still uses hardcoded paths - see https://github.com/Kitware/CMake/blob/master/Modules/FindGTK2.cmake#L280.

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info

flokli commented 3 years ago

still relevant.

Apteryks commented 7 months ago

I stumbled on this using Guix while trying to build Overgrowth. Same problem. Annoying.

Apteryks commented 7 months ago

I could make it work by specifying some extra CMAKE_PREFIX_PATH, like so:

        ;; Help CMake's FindGTK2.cmake, which doesn't look under lib/include
        ;; for the glibconfig.h and gdkconfig.h headers, among other problems,
        ;; which causes GTK2_INCLUDE_DIRS to be empty.
        #~(list (string-append "-DCMAKE_PREFIX_PATH="
                               #$(this-package-input "gtk+") "/lib/;"
                               #$(this-package-input "glib") "/lib"))

Which means that FindGTK2.cmake already mostly works, and would simply need to be modified like this:

1 file changed, 3 insertions(+)
Modules/FindGTK2.cmake | 3 +++

modified   Modules/FindGTK2.cmake
@@ -285,6 +285,9 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
     foreach(_d ${_gtk_packages})
         list(APPEND _suffixes ${_d})
         list(APPEND _suffixes ${_d}/include) # for /usr/lib/gtk-2.0/include
+        # Guix does not add lib/ to the CMAKE_PREFIX_PATH, so manually do so here.
+        list(APPEND _suffixes lib/${_d})
+        list(APPEND _suffixes lib/${_d}/include)
     endforeach()

     if(GTK2_DEBUG)

Alternatively, the CMAKE_PREFIX_PATH search path in Guix could be modified to not only include the root installation prefix of all packages but also their $prefix/lib directory.

Apteryks commented 7 months ago

I've opened a merge request to the Kitware folks here: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/9417