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

build-sys: fix cross-compilation failure caused by building/executing packcc #2747

Merged
merged 3 commits into from
Dec 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ACLOCAL_AMFLAGS = -I m4
Copy link
Member Author

@leleliu008 leleliu008 Dec 2, 2020

Choose a reason for hiding this comment

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

aclocal -I m4

Note that if you use aclocal from Automake to generate aclocal.m4, you must also set ACLOCAL_AMFLAGS = -I dir in your top-level Makefile.am. Due to a limitation in the Autoconf implementation of autoreconf, these include directives currently must be set on a single line in Makefile.am, without any backslash-newlines.

doc


include $(top_srcdir)/source.mak

EXTRA_DIST = README.md autogen.sh \
Expand All @@ -9,7 +11,7 @@ EXTRA_DIST = README.md autogen.sh \
misc/ctags-optlib-mode.el \
misc/mk-interactive-request.sh misc/roundtrip misc/tinst \
misc/packcc/.gitignore misc/packcc/LICENSE.txt \
misc/packcc/README.md \
misc/packcc/README.md misc/packcc/packcc.c \
misc/validators/validator-jq \
misc/validators/validator-KNOWN-INVALIDATION \
misc/validators/validator-NONE \
Expand All @@ -28,6 +30,7 @@ CLEANFILES =
MOSTLYCLEANFILES =

clean-local:
rm -f packcc$(BUILD_EXEEXT)
@if test "$(top_srcdir)" != "$(top_builddir)"; then \
rm -rf $(OPTLIB2C_SRCS); \
fi
Expand All @@ -36,18 +39,16 @@ bin_PROGRAMS = ctags
noinst_LIBRARIES = libctags.a

noinst_PROGRAMS =
noinst_PROGRAMS += packcc
noinst_PROGRAMS += mini-geany

packcc_CPPFLAGS =
packcc_CFLAGS =
packcc_CFLAGS += $(EXTRA_CFLAGS)
dist_packcc_SOURCES = $(PACKCC_SRCS)

if HAVE_STRNLEN
packcc_CPPFLAGS += -DUSE_SYSTEM_STRNLEN
if HAVE_STRNLEN_FOR_BUILD
EXTRA_CPPFLAGS_FOR_BUILD = -DUSE_SYSTEM_STRNLEN
endif

PACKCC = $(top_builddir)/packcc$(BUILD_EXEEXT)

$(PACKCC):
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(EXTRA_CPPFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@ $(top_srcdir)/misc/packcc/packcc.c
Comment on lines +48 to +51
Copy link
Member Author

Choose a reason for hiding this comment

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

build packcc don't follow The Uniform Naming Scheme. because automake auto append $(EXEEXT) to *_PROGRAMS when generating the Makefile, but here we want to use $(BUILD_EXEEXT).


if USE_READCMD
bin_PROGRAMS+= readtags
Expand Down Expand Up @@ -143,14 +144,13 @@ endif
packcc_verbose = $(packcc_verbose_@AM_V@)
packcc_verbose_ = $(packcc_verbose_@AM_DEFAULT_V@)
packcc_verbose_0 = @echo PACKCC " $@";
PACKCC = $(top_builddir)/packcc$(EXEEXT)
SUFFIXES += .peg
.peg.c:
$(packcc_verbose)$(PACKCC) -i \"general.h\" -o $(top_builddir)/peg/$(*F) "$<"
.peg.h:
$(packcc_verbose)$(PACKCC) -i \"general.h\" -o $(top_builddir)/peg/$(*F) "$<"
# You cannot use $(PACKCC) as a target name here.
$(PEG_SRCS) $(PEG_HEADS): packcc$(EXEEXT) Makefile
$(PEG_SRCS) $(PEG_HEADS): $(PACKCC) Makefile
dist_libctags_a_SOURCES = $(ALL_LIB_HEADS) $(ALL_LIB_SRCS)

ctags_CPPFLAGS = $(libctags_a_CPPFLAGS)
Expand Down
43 changes: 43 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,48 @@ jobs:
# make check roundtrip CIRCLECI=1
make units CIRCLECI=1 CATEGORIES=parser-varlink

fedora33_cross_aarch64:
working_directory: ~/universal-ctags
docker:
- image: docker.io/library/fedora:33
steps:
- run:
name: Install tools
command: |
dnf -y install git gcc autoconf automake make
- run:
name: Prepare repo file for install cross compiler
command: |
curl -o /etc/yum.repos.d/lantw44-aarch64-linux-gnu-toolchain-fedora-33.repo https://copr.fedorainfracloud.org/coprs/lantw44/aarch64-linux-gnu-toolchain/repo/fedora-33/lantw44-aarch64-linux-gnu-toolchain-fedora-33.repo
- run:
name: Install the cross compiler for aarch64
command: |
dnf -y install aarch64-linux-gnu-binutils aarch64-linux-gnu-gcc aarch64-linux-gnu-glibc
- checkout
- run:
name: Build ctags for aarch64
command: |
bash ./autogen.sh
mkdir out
./configure --host=aarch64-linux-gnu \
--prefix=`pwd`/out \
--enable-static \
--disable-seccomp \
CC=/usr/bin/aarch64-linux-gnu-gcc \
CPP=/usr/bin/aarch64-linux-gnu-cpp \
AR=/usr/bin/aarch64-linux-gnu-gcc-ar \
RANLIB=/usr/bin/aarch64-linux-gnu-gcc-ranlib \
CC_FOR_BUILD=/usr/bin/gcc
make -j 2
- run:
name: Install locally
command: |
make install
- run:
name: Test
command: |
test -f out/bin/ctags

workflows:
version: 2
build_and_test:
Expand All @@ -169,3 +211,4 @@ workflows:
- fedora_distcheck
- centos_make
- fedora32_gmake
- fedora33_cross_aarch64
35 changes: 35 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ uname -mrsv 2>/dev/null
AM_INIT_AUTOMAKE([foreign subdir-objects tar-ustar])
AM_SILENT_RULES([yes])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
Copy link
Member Author

@leleliu008 leleliu008 Dec 2, 2020

Choose a reason for hiding this comment

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


AC_CANONICAL_BUILD
AC_CANONICAL_HOST
Expand Down Expand Up @@ -240,6 +241,25 @@ AC_PROG_CC_C99
AC_PROG_RANLIB
AC_C_BIGENDIAN

# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
AX_PROG_CC_FOR_BUILD
Comment on lines +244 to +245
Copy link
Member Author

Choose a reason for hiding this comment

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

inset a ready-to-use macro to support cross-compilation.


# We need to compile and run a program on the build machine.
AC_MSG_CHECKING(for cc for build)
if test "$cross_compiling" = "yes"; then
CC_FOR_BUILD="${CC_FOR_BUILD-cc}"
else
CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
CFLAGS_FOR_BUILD="${CFLAGS_FOR_BUILD-$CFLAGS}"
CPPFLAGS_FOR_BUILD="${CPPFLAGS_FOR_BUILD-$CPPFLAGS}"
LDFLAGS_FOR_BUILD="${LDFLAGS_FOR_BUILD-$LDFLAGS}"
fi
AC_MSG_RESULT($CC_FOR_BUILD)
AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler])
AC_ARG_VAR(CFLAGS_FOR_BUILD,[CFLAGS for build system C compiler])
AC_ARG_VAR(CPPFLAGS_FOR_BUILD,[CPPFLAGS for build system C compiler])
AC_ARG_VAR(LDFLAGS_FOR_BUILD,[LDFLAGS for build system C compiler])
Comment on lines +258 to +261
Copy link
Member Author

Choose a reason for hiding this comment

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

let user config those variables when cross-compilation.


if test "${with_sparse_cgcc}" = "yes"; then
REAL_CC="${CC}"
CC="cgcc"
Expand Down Expand Up @@ -706,6 +726,21 @@ AC_CHECK_DECLS([strnlen],[have_strnlen=yes],[],[
])
AM_CONDITIONAL(HAVE_STRNLEN, test "x$have_strnlen" = xyes)

AC_MSG_CHECKING(whether strnlen is declared for build)
TEMP_DIR_FOR_CHECKING=$(mktemp -d || exit 1)
cat > "$TEMP_DIR_FOR_CHECKING/test.c" <<EOF
#include<string.h>
int main() { strnlen("abcd",1); return 0;}
EOF

if $CC_FOR_BUILD $CPPFLAGS_FOR_BUILD $CFLAGS_FOR_BUILD -o "$TEMP_DIR_FOR_CHECKING/test.o" "$TEMP_DIR_FOR_CHECKING/test.c" > /dev/null 2>&1 ; then
have_strnlen_for_build=yes
else
have_strnlen_for_build=no
fi
AC_MSG_RESULT($have_strnlen_for_build)
AM_CONDITIONAL(HAVE_STRNLEN_FOR_BUILD, test "x$have_strnlen_for_build" = xyes)

if test "$CTAGS_NAME_EXECUTABLE" != ctags ; then
AC_MSG_NOTICE(Changing name of 'ctags' for $CTAGS_NAME_EXECUTABLE)
fi
Expand Down
46 changes: 46 additions & 0 deletions docs/autotools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,49 @@ To completely change the program's name run the following:
$ ./configure --program-transform-name='s/ctags/my_ctags/; s/etags/myemacs_tags/'

Please remember there is also an 'etags' installed alongside 'ctags' which you may also want to rename as shown above.

Cross-compilation
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

The way of cross-compilation is a bit complicated because the
build-system of ctags uses `packcc`, a code generator written in C
language. It means that two C compilers should be installed on you build machine;
one for compiling `packcc`, another for compiling `ctags`.

We provide two sets of configure variables to affect these two C compilers:
`CC`, `CFLAGS`, `CPPFLAGS`, `LDFLAGS` variables affect the compiler who compiles `ctags`.
`CC_FOR_BUILD`, `CPPFLAGS_FOR_BUILD`, `CPPFLAGS_FOR_BUILD`, `LDFLAGS_FOR_BUILD` variables
affect the compiler who compiles `packcc`.

When native-compiling, `FOO_FOR_BUILD` is the same as `FOO`.

Here is an example show you how to use these configure variables:

::

$ mkdir ./out
$ configure \
--host=armv7a-linux-androideabi \
--prefix=`pwd`/out \
--enable-static \
--disable-seccomp \
CC=/usr/local/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi21-clang \
CFLAGS='-v' \
CPP='/usr/local/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi21-clang -E' \
CPPFLAGS='-I/Users/leleliu008/.ndk-pkg/pkg/jansson/armeabi-v7a/include -I/Users/leleliu008/.ndk-pkg/pkg/libyaml/armeabi-v7a/include -I/Users/leleliu008/.ndk-pkg/pkg/libxml2/armeabi-v7a/include -I/Users/leleliu008/.ndk-pkg/pkg/libiconv/armeabi-v7a/include --sysroot /usr/local/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -Qunused-arguments -Dftello=ftell -Dfseeko=fseek' \
LDFLAGS='-L/Users/leleliu008/.ndk-pkg/pkg/jansson/armeabi-v7a/lib -L/Users/leleliu008/.ndk-pkg/pkg/libyaml/armeabi-v7a/lib -L/Users/leleliu008/.ndk-pkg/pkg/libxml2/armeabi-v7a/lib -L/Users/leleliu008/.ndk-pkg/pkg/libiconv/armeabi-v7a/lib --sysroot /usr/local/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/sysroot' \
AR=/usr/local/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ar \
RANLIB=/usr/local/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ranlib \
CC_FOR_BUILD=/usr/bin/cc \
CFLAGS_FOR_BUILD='-v' \
PKG_CONFIG_PATH=/Users/leleliu008/.ndk-pkg/pkg/libiconv/armeabi-v7a/lib/pkgconfig:/Users/leleliu008/.ndk-pkg/pkg/libxml2/armeabi-v7a/lib/pkgconfig:/Users/leleliu008/.ndk-pkg/pkg/libyaml/armeabi-v7a/lib/pkgconfig:/Users/leleliu008/.ndk-pkg/pkg/jansson/armeabi-v7a/lib/pkgconfig \
PKG_CONFIG_LIBDIR=/Users/leleliu008/.ndk-pkg/pkg
...
$ make
...
$ make install
...
$ ls out/bin
ctags readtags

Simpler example for `aarch64-linux-gnu` can be found in `circle.yml` in the source tree.
139 changes: 139 additions & 0 deletions m4/ax_prog_cc_for_build.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# ===========================================================================
# 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 <bonzini@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 18

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_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])
AC_PROG_CC
_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
])