Skip to content

[Bug](build): missing '-shared' flag causes 'undefined symbol: main' linker error when cross-compiling #3363

Closed

Description

@kengoon

OS: MacOS 26.6 (M chip)
Python: 3.14
Kivy: 3.0 (master)

when p4a starts building kivy 3.0 it fails with this error:

clang++: warning: argument unused during compilation: '-bundle' [-Wunused-command-line-argument]
clang++: warning: argument unused during compilation: '-undefined dynamic_lookup' [-Wunused-command-line-argument]
ld.lld: error: undefined symbol: main
>>> referenced by crtbegin.c
>>>               /Users/kengoon/.buildozer/android/platform/android-ndk-r28c/toolchains/llvm/prebuilt/darwin-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o:(_start_main)
>>> referenced by crtbegin.c
>>>               /Users/kengoon/.buildozer/android/platform/android-ndk-r28c/toolchains/llvm/prebuilt/darwin-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o:(_start_main)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
 error: command '/opt/homebrew/bin/ccache' failed with exit code 1

but when I add " -shared" to LDFLAGS (this code below) it works fine:

# Taken from CythonRecipe
env['LDFLAGS'] = env['LDFLAGS'] + ' -L{} '.format(
self.ctx.get_libs_dir(arch.arch) +
' -L{} '.format(self.ctx.libs_dir) +
' -L{}'.format(join(self.ctx.bootstrap.build_dir, 'obj', 'local',
arch.arch)))

I wanted to make a PR but I'm new on building with mac and I don't know whether adding -shared will break linux platform (not free to test on linux atm)

Activity

  1. T-Dynamos commented on Aug 4, 2026

    @T-Dynamos
    Member

    It's a general problem with cross compiling for Android from Mac.

    Build system assumes we are building for mac and injects mac related flags. This works fine on linux as Android is effectively a linux.

  2. self-assigned this
    on Aug 31, 2026
  3. AndreMiras commented on Aug 31, 2026

    @AndreMiras
    Member

    Thanks for reporting.
    I think the root cause is that p4a never sets LDCXXSHARED, only LDSHARED.
    You can see it on your machine:

    python -c "import sysconfig; print(sysconfig.get_config_var('LDCXXSHARED'))"

    On macOS that prints roughly clang++ -bundle -undefined dynamic_lookup, on
    Linux g++ -pthread -shared ....

    So on macOS the link becomes NDK clang++ -bundle -undefined dynamic_lookup ...
    On Linux -shared survives, which is why the platform difference exists. That also answers your question: adding -shared to LDFLAGS won't break Linux, it's just a duplicate flag there.
    But it fixes only the kivy recipe, and LDFLAGS also feeds autoconf-style link tests in other recipes.

    A more targeted fix could be in in Arch.get_env():

    env['LDSHARED'] = env['CC'] + ' ' + ' '.join(self.common_ldshared)
    env['LDCXXSHARED'] = env['CXX'] + ' ' + ' '.join(self.common_ldshared)

    and the matching line in the kivy recipe next to the existing LDSHARED
    override:

    env['LDCXXSHARED'] = env['CXX'] + ' -shared'

    This is host-independent, so it should be a no-op on Linux CI while fixing macOS, and it covers every recipe with C++ extensions rather than just kivy.

    I'll open a PR to address
    Edit: #3371

  4. added 2 commits that reference this issue on Sep 1, 2026
    43c6041
    3d8bd98
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions