Hi folks. Wasn't sure how much dev was still being done on this, but hopefully this is still of use to others. I wanted to get GNU Go running on a Remarkable (and then eventually build a frontend), but cross-compilation was hard, due to the fun of the programs in the "patterns" folder being used at build time. I've seen earlier methods described with multiple configure runs and deleting some files, but I wanted something a little more reproducible. The attached patch against the "ttn-maint" branch (which as best I could tell was the most up-to-date branch so I didn't need half a dozen other fixes as well) enables cross-compile in a single configure/make sequence. The hard part was that the programs in "patterns" use libraries from other folders that are also used by the host machine. To solve this, the relevant folders now have a lib<foo>-host.a build as well as a lib<foo>.a build. The latter is for the compile target, the former is for the host target. This is done in a pretty crude way, but seems to work so far. There's a little bit of hardcoding of the ranlib build machine command name that I haven't fixed, as couldn't find an equivalent of AX_PROG_CC_FOR_BUILD for ranlib.
https://github.com/palfrey/gnugo/pull/1 also has some other patches so I could do a CI run using the Toltec (https://toltec-dev.org/) build images for Remarkable but I'm assuming you've got no interest in Github actions patches, and TBH once you've got cross-compile working the Remarkable works just fine. Enjoy! Tom Parker-Shemilt
From ed1fa08c00d0571fc4416fb0649c64806854a8b0 Mon Sep 17 00:00:00 2001 From: Tom Parker-Shemilt <palf...@tevp.net> Date: Wed, 4 Oct 2023 23:21:22 +0100 Subject: [PATCH] Working cross-compile build This enables cross-compile in a single configure/make sequence. The hard part was that there's a variety of programs in patterns that get used at compile time, and so they need to be compiled for the build machine, but they use libraries from other folders that are also used by the host machine. To solve this, the relevant folders have a lib<foo>-host.a build as well as a lib<foo>.a build. The latter is for the compile target, the former is for the host target. This is done in a pretty crude way, but seems to work so far. Signed-off-by: Tom Parker-Shemilt <palf...@tevp.net> --- configure.ac | 3 + engine/Makefile.am | 26 ++++++- m4/ax_prog_cc_for_build.m4 | 155 +++++++++++++++++++++++++++++++++++++ patterns/Makefile.am | 33 ++++++-- sgf/Makefile.am | 18 ++++- utils/Makefile.am | 21 ++++- 6 files changed, 245 insertions(+), 11 deletions(-) create mode 100644 m4/ax_prog_cc_for_build.m4 diff --git a/configure.ac b/configure.ac index 3ff08a7f..254e17bf 100644 --- a/configure.ac +++ b/configure.ac @@ -125,7 +125,10 @@ AC_ARG_ENABLE(socket-support, [ --disable-socket-support don't compile GTP over TCP/IP support --enable-socket-support compile TCP/IP support (default)]) +AC_CONFIG_MACRO_DIR([m4]) + AC_PROG_CC +AX_PROG_CC_FOR_BUILD dnl for automake 1.4.x AC_EXEEXT diff --git a/engine/Makefile.am b/engine/Makefile.am index d0203034..f4a37985 100644 --- a/engine/Makefile.am +++ b/engine/Makefile.am @@ -14,7 +14,7 @@ noinst_HEADERS = cache.h gnugo.h hash.h clock.h readconnect.h \ influence.h liberty.h move_reasons.h board.h # preconfigured settings for various configurations -noinst_LIBRARIES = libengine.a libboard.a +noinst_LIBRARIES = libengine.a libengine-host.a libboard.a libboard-host.a libengine_a_SOURCES = \ aftermath.c \ @@ -61,3 +61,27 @@ libboard_a_SOURCES = \ boardlib.c \ hash.c \ printutils.c + +LINK_FOR_BUILD.c = $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) +COMPILE_FOR_BUILD = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) + +%-host.o : %.c + $(AM_V_CC)$(COMPILE_FOR_BUILD) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po + +libengine_host_a_SOURCES = +libengine_host_a_DEPENDENCIES = $(patsubst %.c,%-host.o,$(libengine_a_SOURCES)) + +libengine-host.a: $(libengine_host_a_OBJECTS) $(libengine_host_a_DEPENDENCIES) + rm -f libengine-host.a + $(AM_V_AR)$(libengine_host_a_AR) libengine-host.a $(libengine_host_a_OBJECTS) $(libengine_host_a_DEPENDENCIES) + x86_64-linux-gnu-ranlib libengine-host.a + +libboard_host_a_SOURCES = +libboard_host_a_DEPENDENCIES = $(patsubst %.c,%-host.o,$(libboard_a_SOURCES)) + +libboard-host.a: $(libboard_host_a_OBJECTS) $(libboard_host_a_DEPENDENCIES) + rm -f libboard-host.a + $(AM_V_AR)$(libboard_host_a_AR) libboard-host.a $(libboard_host_a_OBJECTS) $(libboard_host_a_DEPENDENCIES) + x86_64-linux-gnu-ranlib libboard-host.a diff --git a/m4/ax_prog_cc_for_build.m4 b/m4/ax_prog_cc_for_build.m4 new file mode 100644 index 00000000..1db8d73f --- /dev/null +++ b/m4/ax_prog_cc_for_build.m4 @@ -0,0 +1,155 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PROG_CC_FOR_BUILD +# +# DESCRIPTION +# +# This macro searches for a C compiler that generates native executables, +# that is a C compiler that surely is not a cross-compiler. This can be +# useful if you have to generate source code at compile-time like for +# example GCC does. +# +# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything +# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). +# The value of these variables can be overridden by the user by specifying +# a compiler with an environment variable (like you do for standard CC). +# +# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object +# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if +# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are +# substituted in the Makefile. +# +# LICENSE +# +# Copyright (c) 2008 Paolo Bonzini <bonz...@gnu.org> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 21 + +AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) +AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl + +dnl Use the standard macros, but make them use other variable names +dnl +pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl +pushdef([ac_cv_prog_cc_c89], ac_cv_build_prog_cc_c89)dnl +pushdef([ac_cv_prog_cc_c99], ac_cv_build_prog_cc_c99)dnl +pushdef([ac_cv_prog_cc_c11], ac_cv_build_prog_cc_c11)dnl +pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl +pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl +pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl +pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl +pushdef([ac_cv_c_compiler_gnu], ac_cv_build_c_compiler_gnu)dnl +pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl +pushdef([ac_cv_objext], ac_cv_build_objext)dnl +pushdef([ac_exeext], ac_build_exeext)dnl +pushdef([ac_objext], ac_build_objext)dnl +pushdef([CC], CC_FOR_BUILD)dnl +pushdef([CPP], CPP_FOR_BUILD)dnl +pushdef([GCC], GCC_FOR_BUILD)dnl +pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl +pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl +pushdef([EXEEXT], BUILD_EXEEXT)dnl +pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl +pushdef([OBJEXT], BUILD_OBJEXT)dnl +pushdef([host], build)dnl +pushdef([host_alias], build_alias)dnl +pushdef([host_cpu], build_cpu)dnl +pushdef([host_vendor], build_vendor)dnl +pushdef([host_os], build_os)dnl +pushdef([ac_cv_host], ac_cv_build)dnl +pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl +pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl +pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl +pushdef([ac_cv_host_os], ac_cv_build_os)dnl +pushdef([ac_tool_prefix], ac_build_tool_prefix)dnl +pushdef([am_cv_CC_dependencies_compiler_type], am_cv_build_CC_dependencies_compiler_type)dnl +pushdef([am_cv_prog_cc_c_o], am_cv_build_prog_cc_c_o)dnl +pushdef([cross_compiling], cross_compiling_build)dnl + +cross_compiling_build=no + +ac_build_tool_prefix= +AS_IF([test -n "$build"], [ac_build_tool_prefix="$build-"], + [test -n "$build_alias"],[ac_build_tool_prefix="$build_alias-"]) + +AC_LANG_PUSH([C]) + +dnl The pushdef([ac_cv_c_compiler_gnu], ...) currently does not cover +dnl the use of this variable in _AC_LANG_COMPILER_GNU called by +dnl AC_PROG_CC. Unset this cache variable temporarily as a workaround. +was_set_c_compiler_gnu=${[ac_cv_c_compiler_gnu]+y} +AS_IF([test ${was_set_c_compiler_gnu}], + [saved_c_compiler_gnu=$[ac_cv_c_compiler_gnu] + AS_UNSET([[ac_cv_c_compiler_gnu]])]) + +AC_PROG_CC + +dnl Restore ac_cv_c_compiler_gnu +AS_IF([test ${was_set_c_compiler_gnu}], + [[ac_cv_c_compiler_gnu]=$[saved_c_compiler_gnu]]) + +_AC_COMPILER_EXEEXT +_AC_COMPILER_OBJEXT +AC_PROG_CPP + +dnl Restore the old definitions +dnl +popdef([cross_compiling])dnl +popdef([am_cv_prog_cc_c_o])dnl +popdef([am_cv_CC_dependencies_compiler_type])dnl +popdef([ac_tool_prefix])dnl +popdef([ac_cv_host_os])dnl +popdef([ac_cv_host_vendor])dnl +popdef([ac_cv_host_cpu])dnl +popdef([ac_cv_host_alias])dnl +popdef([ac_cv_host])dnl +popdef([host_os])dnl +popdef([host_vendor])dnl +popdef([host_cpu])dnl +popdef([host_alias])dnl +popdef([host])dnl +popdef([OBJEXT])dnl +popdef([LDFLAGS])dnl +popdef([EXEEXT])dnl +popdef([CPPFLAGS])dnl +popdef([CFLAGS])dnl +popdef([GCC])dnl +popdef([CPP])dnl +popdef([CC])dnl +popdef([ac_objext])dnl +popdef([ac_exeext])dnl +popdef([ac_cv_objext])dnl +popdef([ac_cv_exeext])dnl +popdef([ac_cv_c_compiler_gnu])dnl +popdef([ac_cv_prog_cc_g])dnl +popdef([ac_cv_prog_cc_cross])dnl +popdef([ac_cv_prog_cc_works])dnl +popdef([ac_cv_prog_cc_c89])dnl +popdef([ac_cv_prog_gcc])dnl +popdef([ac_cv_prog_CPP])dnl + +dnl restore global variables ac_ext, ac_cpp, ac_compile, +dnl ac_link, ac_compiler_gnu (dependant on the current +dnl language after popping): +AC_LANG_POP([C]) + +dnl Finally, set Makefile variables +dnl +AC_SUBST(BUILD_EXEEXT)dnl +AC_SUBST(BUILD_OBJEXT)dnl +AC_SUBST([CFLAGS_FOR_BUILD])dnl +AC_SUBST([CPPFLAGS_FOR_BUILD])dnl +AC_SUBST([LDFLAGS_FOR_BUILD])dnl +]) diff --git a/patterns/Makefile.am b/patterns/Makefile.am index 4fedf35c..59098405 100644 --- a/patterns/Makefile.am +++ b/patterns/Makefile.am @@ -38,9 +38,29 @@ EXTRA_DIST = $(DTR)\ fuseki9.dbz\ CMakeLists.txt -mkpat_SOURCES = mkpat.c transform.c dfa.c +LINK_FOR_BUILD.c = $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) +COMPILE_FOR_BUILD = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -mkpat_LDADD = ../utils/libutils.a +%-host.o : %.c + $(AM_V_CC)$(COMPILE_FOR_BUILD) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po + +mkpat_SOURCES = +mkpat_DEPENDENCIES = $(patsubst %.c,%-host.o,mkpat.c transform.c dfa.c) + +HOST_PROGS = $(noinst_PROGRAMS) + +define HOST_PROGRAM_template = + $$($(1)_OBJECTS) : CC=$(CC_FOR_BUILD) + $(1)$(EXEEXT): $$($(1)_OBJECTS) $$($(1)_DEPENDENCIES) $$(EXTRA_$(1)_DEPENDENCIES) + @rm -f $(1)$(EXEEXT) + $(AM_V_CCLD)$(LINK_FOR_BUILD.c) -o $(1)$(EXEEXT) $$($(1)_DEPENDENCIES) $$($(1)_OBJECTS) $($(1)_LDADD) $(LIBS) +endef + +$(foreach prog,$(HOST_PROGS),$(eval $(call HOST_PROGRAM_template,$(prog)))) + +mkpat_LDADD = ../utils/libutils-host.a if DFA_ENABLED DFAFLAGS = -D -m @@ -49,22 +69,21 @@ DFAFLAGS = endif joseki_SOURCES = joseki.c -joseki_LDADD = ../engine/libboard.a ../sgf/libsgf.a ../utils/libutils.a +joseki_LDADD = ../engine/libboard-host.a ../sgf/libsgf-host.a ../utils/libutils-host.a joseki_AM_CPPFLAGS = $(GNU_GO_WARNINGS) -I$(top_srcdir)/sgf mkeyes_SOURCES = mkeyes.c +$(mkeyes_OBJECTS) : CC=$(CC_FOR_BUILD) mkeyes_LDADD = ../utils/libutils.a mkmcpat_SOURCES = mkmcpat.c ../engine/globals.c -mkmcpat_LDADD = ../engine/libengine.a ../sgf/libsgf.a ../utils/libutils.a +mkmcpat_LDADD = ../engine/libengine-host.a ../sgf/libsgf-host.a ../utils/libutils-host.a mkmcpat_AM_CPPFLAGS = $(GNU_GO_WARNINGS) extract_fuseki_SOURCES = extract_fuseki.c -# Yes, we currently need duplicate libengine.a and libpatterns.a. extract_fuseki_LDADD = ../engine/libengine.a libpatterns.a\ - ../engine/libengine.a libpatterns.a\ ../sgf/libsgf.a ../utils/libutils.a extract_fuseki_AM_CPPFLAGS = $(GNU_GO_WARNINGS) -I$(top_srcdir)/sgf uncompress_fuseki_SOURCES = uncompress_fuseki.c -uncompress_fuseki_LDADD = ../utils/libutils.a ../engine/libboard.a ../sgf/libsgf.a +uncompress_fuseki_LDADD = ../utils/libutils-host.a ../engine/libboard-host.a ../sgf/libsgf-host.a compress_fuseki_SOURCES = compress_fuseki.c noinst_HEADERS = patterns.h eyes.h dfa.h dfa-mkpat.h diff --git a/sgf/Makefile.am b/sgf/Makefile.am index eb5ae556..8a492383 100644 --- a/sgf/Makefile.am +++ b/sgf/Makefile.am @@ -13,7 +13,7 @@ DISTCLEANFILES = *~ AM_CPPFLAGS = $(GNU_GO_WARNINGS) -I$(top_srcdir)/utils -noinst_LIBRARIES = libsgf.a +noinst_LIBRARIES = libsgf.a libsgf-host.a libsgf_a_SOURCES = \ sgf_utils.c \ @@ -25,3 +25,19 @@ libsgf_a_SOURCES = \ sgf_properties: cat $(srcdir)/sgf_properties.def $(srcdir)/sgf_extras.def |\ ./sgfgen > sgf_properties.h + +LINK_FOR_BUILD.c = $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) +COMPILE_FOR_BUILD = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) + +%-host.o : %.c + $(AM_V_CC)$(COMPILE_FOR_BUILD) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po + +libsgf_host_a_SOURCES = +libsgf_host_a_DEPENDENCIES = $(patsubst %.c,%-host.o,$(libsgf_a_SOURCES)) + +libsgf-host.a: $(libsgf_host_a_OBJECTS) $(libsgf_host_a_DEPENDENCIES) + rm -f libsgf-host.a + $(AM_V_AR)$(libsgf_host_a_AR) libsgf-host.a $(libsgf_host_a_OBJECTS) $(libsgf_host_a_DEPENDENCIES) + x86_64-linux-gnu-ranlib libsgf-host.a diff --git a/utils/Makefile.am b/utils/Makefile.am index d9e420d2..8e66b3bb 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,10 +1,27 @@ -noinst_LIBRARIES = libutils.a +noinst_LIBRARIES = libutils.a libutils-host.a EXTRA_DIST = CMakeLists.txt -libutils_a_SOURCES = getopt.c getopt1.c random.c gg_utils.c winsocket.c +utils_sources = getopt.c getopt1.c random.c gg_utils.c winsocket.c +libutils_a_SOURCES = $(utils_sources) noinst_HEADERS = gg-getopt.h random.h gg_utils.h winsocket.h # Remove these files here... they are created locally DISTCLEANFILES = *~ + +LINK_FOR_BUILD.c = $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) +COMPILE_FOR_BUILD = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) + +%-host.o : %.c + $(AM_V_CC)$(COMPILE_FOR_BUILD) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po + +libutils_host_a_SOURCES = +libutils_host_a_DEPENDENCIES = $(patsubst %.c,%-host.o,$(utils_sources)) + +libutils-host.a: $(libutils_host_a_OBJECTS) $(libutils_host_a_DEPENDENCIES) + rm -f libutils-host.a + $(AM_V_AR)$(libutils_host_a_AR) libutils-host.a $(libutils_host_a_OBJECTS) $(libutils_host_a_DEPENDENCIES) + x86_64-linux-gnu-ranlib libutils-host.a -- 2.30.2
_______________________________________________ gnugo-devel mailing list gnugo-devel@gnu.org https://lists.gnu.org/mailman/listinfo/gnugo-devel