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

Failed to build a simple gtk-fortran example: how to link with gtk-4-fortran? #487

Closed
vmagnin opened this issue Jun 3, 2021 · 13 comments
Closed
Labels
packaging Related to porting or packaging a project to fpm

Comments

@vmagnin
Copy link
Member

vmagnin commented Jun 3, 2021

I have created a small repository with the example I am trying to build as an fpm project:
https://github.com/vmagnin/gtkzero_fpm
It is the gtkzero_gapp.f90 available in the gtk-fortran gtk4 branch: it just opens an empty GTK 4 window. As the original file contains the main program and a handlers module, I have put that module in src/handlers.f90. The main program has been renamed: app/main.f90.

My fpm version is 0.2.0 alpha. I have tried adding link = "gtk-4-fortran" in the [build] section of the fpm.toml file, but it does not change anything.

$ fpm build --flag '$(pkg-config --cflags --libs gtk-4-fortran)'
Unable to find source for module dependency: "gtk" used by "app/main.f90"
ERROR STOP 1

Error termination. Backtrace:
#0  0x7f559b678820 in ???
#1  0x7f559b679379 in ???
#2  0x7f559b67ab02 in ???
#3  0x55e89918f6a5 in __fpm_MOD_cmd_build
        at ././src/fpm.f90:260
#4  0x55e89917944f in MAIN__
        at app/main.f90:26
#5  0x55e89917944f in main
        at app/main.f90:9

Same error if I replace the apostrophes by double quotes.

This is the output of the pkg-config command on my machine:

$ pkg-config --cflags --libs gtk-4-fortran
-rdynamic -mfpmath=sse -msse -msse2 -pthread -I/usr/local/include/gtk-4-fortran -I/usr/include/gtk-4.0 -I/usr/include/gio-unix-2.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/harfbuzz -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/uuid -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/graphene-1.0 -I/usr/lib/x86_64-linux-gnu/graphene-1.0/include -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -Xlinker -R/usr/local/lib -lgtk-4-fortran -lgtk-4 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lvulkan -lgraphene-1.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0

The gtk-fortran modules are here:

$ ls /usr/local/include/gtk-4-fortran
cairo.mod          g.mod                 gtk_hl_button.mod     gtk_hl_entry.mod     gtk_hl_spin_slider.mod  handlers_gtk_fortran.mod
gdk_events.mod     graphene.mod          gtk_hl_chooser.mod    gtk_hl_infobar.mod   gtk_hl_tree.mod         pango.mod
gdk.mod            gsk.mod               gtk_hl_combobox.mod   gtk_hl_misc.mod      gtk.mod                 plplot_extra.mod
gdk_pixbuf_hl.mod  gtk_draw_hl.mod       gtk_hl_container.mod  gtk_hl.mod           gtk_os_dependent.mod    unix_print.mod
gdk_pixbuf.mod     gtk_hl_assistant.mod  gtk_hl_dialog.mod     gtk_hl_progress.mod  gtk_sup.mod
@awvwgk awvwgk added the packaging Related to porting or packaging a project to fpm label Jun 3, 2021
@awvwgk
Copy link
Member

awvwgk commented Jun 3, 2021

External module files have to declared explicitly, see here. In this case it would require an additional entry in the build section:

[build]
link = "gtk-4-fortran"
external-modules = ["gtk", "g"]

@vmagnin
Copy link
Member Author

vmagnin commented Jun 3, 2021

In this case it would require an additional entry in the build section:

My fpm does not like that new line :-(

$ fpm build --flag "$(pkg-config --cflags --libs gtk-4-fortran)"
Key external-modules is not allowed in [build]
ERROR STOP 1

Error termination. Backtrace:
#0  0x7f641f428820 in ???

Perhaps not yet in fpm 0.2.0 ?

@awvwgk
Copy link
Member

awvwgk commented Jun 3, 2021

You're right, it was added with #438 but hasn't been released yet.

@awvwgk
Copy link
Member

awvwgk commented Jun 23, 2021

This might be resolved with the freshly released fpm version 0.3.0

@vmagnin
Copy link
Member Author

vmagnin commented Jun 23, 2021

Thanks @awvwgk for the information,
I will try when I have some time and report here the result.

@vmagnin
Copy link
Member Author

vmagnin commented Jun 23, 2021

@awvwgk
I have just installed fpm 0.3.0 alpha (Ubuntu 21.04).
It's better but the linking fails with the same little test project (https://github.com/vmagnin/gtkzero_fpm):

$ fpm build --flag '$(pkg-config --cflags --libs gtk-4-fortran)'
 + mkdir -p build/dependencies
 + mkdir -p build/gfortran_4E42016360FFAE8D/gtkzero_fpm
 + gfortran -c test/check.f90 $(pkg-config --cflags --libs gtk-4-fortran) -J build/gfortran_4E42016360FFAE8D/gtkzero_fpm -I build/gfortran_4E42016360FFAE8D/gtkzero_fpm  -o build/gfortran_4E42016360FFAE8D/gtkzero_fpm/test_check.f90.o
 + gfortran -c ././src/handlers.f90 $(pkg-config --cflags --libs gtk-4-fortran) -J build/gfortran_4E42016360FFAE8D/gtkzero_fpm -I build/gfortran_4E42016360FFAE8D/gtkzero_fpm  -o build/gfortran_4E42016360FFAE8D/gtkzero_fpm/src_handlers.f90.o
 + ar -rs build/gfortran_4E42016360FFAE8D/gtkzero_fpm/libgtkzero_fpm.a build/gfortran_4E42016360FFAE8D/gtkzero_fpm/src_handlers.f90.o
ar: création de build/gfortran_4E42016360FFAE8D/gtkzero_fpm/libgtkzero_fpm.a
 + gfortran -c app/main.f90 $(pkg-config --cflags --libs gtk-4-fortran) -J build/gfortran_4E42016360FFAE8D/gtkzero_fpm -I build/gfortran_4E42016360FFAE8D/gtkzero_fpm  -o build/gfortran_4E42016360FFAE8D/gtkzero_fpm/app_main.f90.o
 + mkdir -p build/gfortran_4E42016360FFAE8D/app/
 + gfortran  $(pkg-config --cflags --libs gtk-4-fortran) -J build/gfortran_4E42016360FFAE8D/gtkzero_fpm -I build/gfortran_4E42016360FFAE8D/gtkzero_fpm  build/gfortran_4E42016360FFAE8D/gtkzero_fpm/app_main.f90.o build/gfortran_4E42016360FFAE8D/gtkzero_fpm/libgtkzero_fpm.a -lgtk-4-fortran -o build/gfortran_4E42016360FFAE8D/app/gtkzero_fpm
/usr/bin/ld: build/gfortran_4E42016360FFAE8D/gtkzero_fpm/app_main.f90.o: undefined reference to symbol 'gtk_application_new'
/usr/bin/ld : /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libgtk-4.so : erreur lors de l'ajout de symboles : DSO missing from command line
collect2: error: ld returned 1 exit status
 <ERROR> Compilation failed for object "gtkzero_fpm"
STOP 1

Note that if I type the following command, it compiles and runs:

$ gfortran src/handlers.f90 app/main.f90 $(pkg-config --cflags --libs gtk-4-fortran)

@awvwgk
Copy link
Member

awvwgk commented Jun 23, 2021

The problem is that you are adding the libs with the --flag command, and they will end up in-front of the objects in the link line.

You probably have to add the output of pkg-config --libs gtk-4-fortran to the build.link entry in the package manifest, rather than using it with the --flag switch.

@vmagnin
Copy link
Member Author

vmagnin commented Jun 23, 2021

Thanks Sebastian @awvwgk

I have separated the --cflags and --libs parts of the pkg-config command. I am now using the following command:

$  fpm build --flag '$(pkg-config --cflags gtk-4-fortran) -Xlinker -R/usr/local/lib'

In the fpm.toml, I first tried:

link = "gtk-4 pangocairo-1.0 pango-1.0 harfbuzz gdk_pixbuf-2.0 cairo-gobject cairo vulkan graphene-1.0 gio-2.0 gobject-2.0 glib-2.0 gtk-4-fortran"

The problem is that on the compilation command lines, only the first library is prefixed with -l (-lgtk-4 pangocairo-1.0 pango-1.0 harfbuzz gdk_pixbuf-2.0 cairo-gobject cairo vulkan graphene-1.0 gio-2.0 gobject-2.0 glib-2.0 gtk-4-fortran)
I was therefore obliged to add -l in front of all the other libraries:

link = "gtk-4 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lvulkan -lgraphene-1.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lgtk-4-fortran"

In that case, the build is OK with:

$  fpm build --flag '$(pkg-config --cflags gtk-4-fortran) -Xlinker -R/usr/local/lib'

But if I run:

$ fpm run
 + mkdir -p build/gfortran_2A42023B310FA28D/gtkzero_fpm
 + gfortran -c test/check.f90 -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -J build/gfortran_2A42023B310FA28D/gtkzero_fpm -I build/gfortran_2A42023B310FA28D/gtkzero_fpm  -o build/gfortran_2A42023B310FA28D/gtkzero_fpm/test_check.f90.o
 + gfortran -c ./src/handlers.f90 -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -J build/gfortran_2A42023B310FA28D/gtkzero_fpm -I build/gfortran_2A42023B310FA28D/gtkzero_fpm  -o build/gfortran_2A42023B310FA28D/gtkzero_fpm/src_handlers.f90.o
./src/handlers.f90:7:7:

	7 |   use gtk, only: gtk_window_set_default_size, gtk_window_set_title, &
	  |       1
Fatal Error: Cannot open module file ‘gtk.mod’ for reading at (1): Aucun fichier ou dossier de ce type
compilation terminated.
 <ERROR> Compilation failed for object "src_handlers.f90.o"
STOP 1

Finally it runs successfully if I use the --flag options with fpm run:

$ fpm run --flag '$(pkg-config --cflags gtk-4-fortran) -Xlinker -R/usr/local/lib'

@awvwgk
Copy link
Member

awvwgk commented Jun 23, 2021

The problem is that on the compilation command lines, only the first library is prefixed with -l (-lgtk-4 pangocairo-1.0 pango-1.0 harfbuzz gdk_pixbuf-2.0 cairo-gobject cairo vulkan graphene-1.0 gio-2.0 gobject-2.0 glib-2.0 gtk-4-fortran)

build.link takes a list of strings or a single string as shortcut for a list with one entry:

build.link = [
  "gtk-4",
  "pangocairo-1.0",
  "pango-1.0",
  "harfbuzz",
  "gdk_pixbuf-2.0",
  "cairo-gobject",
  "cairo",
  "vulkan",
  "graphene-1.0",
  "gio-2.0",
  "gobject-2.0",
  "glib-2.0",
  "gtk-4-fortran",
]

It's quite a lot of libraries to specify explicitly, unfortunately.

@vmagnin
Copy link
Member Author

vmagnin commented Jun 23, 2021

OK @awvwgk , I should have thought that it must be a list like in my external-modules = ["gtk", "g"] line.

So, now everything is OK with those commands:

$ fpm build --flag '$(pkg-config --cflags gtk-4-fortran) -Xlinker -R/usr/local/lib'

and

$  fpm run --flag '$(pkg-config --cflags gtk-4-fortran) -Xlinker -R/usr/local/lib'

But I don't understand why I am obliged to use --flag with fpm run... (see my previous message for the error message if I don't add the flags). If I go into the build directory and I click on the executable it runs fine. So what does fpm run does?

@vmagnin
Copy link
Member Author

vmagnin commented Jun 23, 2021

Note also that all the libraries are not needed for all programs, that's just for the general case.
For that small example, we just need:

link = [
  "gtk-4",
  "gio-2.0",
  "gobject-2.0",
  "glib-2.0",
  "gtk-4-fortran",
]

@awvwgk
Copy link
Member

awvwgk commented Jun 23, 2021

fpm is stateless, if you use fpm run it will first invoke fpm build to make sure the binary is up-to-date, to select the binary the command line arguments are hashed, therefore every fpm command has to know the full list of flags to select the right build.

Better pkg-config support would resolve this issue of having to use --flag mostly, maybe something like

[dependencies]
gtk-4-fortran.pkg-config = "gtk-4-fortran"

could be an option.

@vmagnin
Copy link
Member Author

vmagnin commented Jun 24, 2021

Thanks for all!
I have added a How to use fpm to build a gtk-fortran project in the gtk-fortran wiki.

@vmagnin vmagnin closed this as completed Jun 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
packaging Related to porting or packaging a project to fpm
Projects
None yet
Development

No branches or pull requests

2 participants