The proper way of forcing a 32-bit compile using CMake

Sorry that there are many similar questions, but I do find that Googling for CMake queries always yields similar-but-not-the-same scenarios, conflicting CMake commands and so on!

I need to force my project to build 32-bit binaries because I have to link with a library which is only available as 32-bit. I diagnosed this based on error messages such as:

/usr/bin/ld: i386 architecture of input file `*external-32bit-lib*' is incompatible with i386:x86-64 output

From what I gather, I should therefore use:

set (CMAKE_CXX_FLAGS "-m32")

This does change things - I now get several errors like:

/usr/bin/ld: i386 architecture of input file `*project-output-lib*' is incompatible with i386:x86-64 output

AND still get the same errors for the external library too. I think this is because the -m32 made gcc generate 32-bit binaries, but ld is still trying for 64-bit output? Further Googling for this problem didn't give any success, so if anyone could verify that I am right and give the correct way of doing this, I would be very grateful!

Many thanks!


If you want to compile and link for 32 bit using cmake use this for creating libraries and binaries:

Creating libraries:

add_library(mylib SHARED my_source.c)
set_target_properties(mylib PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")

creating executables:

add_executable(mybin sources.c)
set_target_properties(mybin PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")

Even if this seems like extra works, I believe a proper solution is to use toolchain file in this case. Something like:

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)

# which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc)
set(CMAKE_C_FLAGS -m32)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_FLAGS -m32)

# here is the target environment located
set(CMAKE_FIND_ROOT_PATH   /usr/i486-linux-gnu )

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Then usage is simply:

$ cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake /path/to/source

The important part here is that one is now able to specify a root dir path (CMAKE_FIND_ROOT_PATH) which should be used to search for third party lib. Indeed your compiler may not be smart enough to know where to search for an x86 Qt library on an x86_64 system.

Having a toolchain file allows one to specify a different one on a par compiler basis, and you should be able to tweak the option when compiling in 32bits from a windows environement.

Nowadays this is extra works since compiling 32bits from an x86_64 Linux OS is pretty much trivial, but this solution will work for other more exotic setup.

For more information on toolchain file, one can check for example:

  • http://www.cmake.org/Wiki/CmakeMingw

CMAKE_CXX_FLAGS only affects the C++ compiler. You probably also have to set the flag for the C compiler:

set (CMAKE_C_FLAGS "-m32")

It sounds like you did not pass m32 to LFLAGS too, or there are old obj files skulking about. Be sure to clean first.

This question is similar to yours: cmake, gcc, cuda and -m32


Use TRY_RUN command by the following source.

size.cpp:

#include <cstdlib>

int main( int argc, char** argv )
{
  size_t size = sizeof(void*);
  if ( size == 4 )
    return 0;
  return 1;
}

CMakeLists.txt:

TRY_RUN(RUN_RESULT_VAR COMPILE_RESULT_VAR ${your_temp_dir} size.cpp RUN_OUTPUT_VARIABLE IS_64_SYSTEM)
IF(IS_64_SYSTEM)
  MESSAGE(FATAL_ERROR "64 compiling not allowed!")
ENDIF(IS_64_SYSTEM)

It will work on all standard compiler.