find_package(PNG) failing to find i386 libs when crosscompiling on x86-64 host?

The situation: my host system is an x86-64 linux system (running ubuntu 18). I’m trying to cross-compile (and test) for x86-32 on this system. Most of what I need to do seems straightforward, and has worked fine for a long time; the gotcha is that I can’t seem to get find_package(PNG) or find_package(JPEG) to find the 32-bit versions that are present on the system.

Mnore details:

My setup for cross-compiling (and cross-testing) is basically:

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install \
  gcc-multilib \
  g++-multilib \
  libjpeg-dev:i386 \
  libpng-dev:i386 \
...
export CC="${CC} -m32"
export CXX="${CXX} -m32"
export LD="${LD} -melf_i386"
...
cmake <my normal cmake args> \
       -D CMAKE_FIND_ROOT_PATH=/usr/lib/i386-linux-gnu \
       -D CMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY"

I’ve tried adding variations of CMAKE_MODULE_PATH, CMAKE_PREFIX_PATH, CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX, PNG_DIR/JPEG_DIR, and probably other things, but I still end up with find_package(PNG) and find_package(JPEG) both failing. I’ve verified by inspection that the packages really are there (under /usr/lib/i386-linux-gnu), but CMake refuses to find them, and I can’t figure out any way to get it to be more verbose about telling me why it’s failing.

BTW, this is using cmake version 3.16.2.

Any suggestions here?

1 Like

You’re not telling CMake that you’re cross-compiling here. Rather than using -m32 flags “behind” CMake’s back, try making a toolchain file (there are also docs on making these around the Web) to let CMake know that you’re cross compiling (you should be able to use CMAKE_CROSSCOMPILING_EMULATOR set to the empty string (not undefined) to indicate that the resulting binaries are natively executable).

I had to try a lot of different sources to piece together what I needed for a toolchain file – yes, there are many docs on the web, but none of them seem particularly definitive or exhaustive. (The CMake doc page could be improved by adding more examples.)

That said, this seems to be working for my use case so far:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR i686)

set(CMAKE_CXX_FLAGS_INIT -m32)
set(CMAKE_C_FLAGS_INIT -m32)

set(CMAKE_EXE_LINKER_FLAGS_INIT -m32)
set(CMAKE_SHARED_LINKER_FLAGS_INIT -m32)
set(CMAKE_MODULE_LINKER_FLAGS_INIT -m32)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Set to empty string to indicate the resulting binaries can be natively executed
set(CMAKE_CROSSCOMPILING_EMULATOR )

Ah, sorry for the aimless direction; I haven’t done many toolchain files myself. The #cmake Slack channel on cpplang.slack.com has folks who are more knowledgeable than I about that specific topic at least.

Do you have specific feedback to this end? The x86_64 → ix86 case seems common enough to just have an example, but any other details would be useful to help us improve the docs.

How does one get an invitation to that Slack channel?

I think you just join it once you have an account using the sidebar. I don’t think there’s any invite-only status on it.

Turns out you go here: https://cpplang-inviter.cppalliance.org/