Linking Ada objects into a C++ shared library

Dear all,

I am currently trying to port a gigantic C/C++/Fortran/Ada project to CMake and got stuck. Everything needs to be compiled into a single shared library which then gets dlopened elsewhere. But I am having a problem with the Ada part of the project.

I have written the following custom command to compile the Ada code:

  get_filename_component(sourcefile ${origin} NAME)
  get_filename_component(target ${origin} NAME_WE)
  configure_file(${origin} ${WORK_DIR}/${sourcefile} COPYONLY)

  add_custom_command(OUTPUT ${WORK_DIR}/${target}.o
    MAIN_DEPENDENCY ${WORK_DIR}/${sourcefile}
    COMMAND gnatmake ARGS -fPIC -O2 -c -i ${WORK_DIR}/${sourcefile}

The results are supposed to go into an OBJECT library which then gets added to main shared lib, like so:

add_library(${TARGET_NAME}_ada_shell OBJECT
set_target_properties(${TARGET_NAME}_ada_shell PROPERTIES LINKER_LANGUAGE C)

add_library(main SHARED

Compiling the Ada sources works fine but the resulting $<TARGET_OBJECTS:${TARGET_NAME}_ada_shell> generator expression is empty.

What am I doing wrong?

Many thanks in advance!

EDIT: CMake 3.5.2, locked-down system, sorry!

You cannot mix custom commands and libraries. add_library() is only able to handle sources for supported languages. So, somefile.adb is simply ignored.

To work-around this, manage all ada source files compilation by custom commands (what you already did) and a custom target (see add_custom_target()). And add explicitly the dependency between targets (add_dependencies()) to ensure compilation.

And to finish, compute the list of ada objects and add them explicitly to the link step of you library.

Something like that:

foreach (...)
  add_custom_command(OUTPUT ${WORK_DIR}/${target}.o ...)
  list(APPEND ADA_OUTPUTS ${WORK_DIR}/${target}.o)

add_library(main SHARED ...)
add_dependencies(main ada_objects)
target_link_libraries(main PRIVATE ${ADA_OUTPUTS})

And FYI, I am currently evaluating the integration of Ada language support in CMake (gnat specifically). I think it is feasible but many changes are required in the code of CMake.
For now, I am just able to pass the initialization step and compile a simple ada executable.

For the fun:

cmake_minimum_required(VERSION 3.19)

project(Tests LANGUAGES Ada)

set(CMAKE_Ada_STANDARD 2012)

add_executable(ada_test hello.adb)
set_property(TARGET ada_test PROPERTY MAIN_NAME hello)

And lauching cmake gives:

-- The Ada compiler identification is GNU 2020
-- Checking whether Ada compiler has -isysroot
-- Checking whether Ada compiler has -isysroot - yes
-- Checking whether Ada compiler supports OSX deployment target flag
-- Checking whether Ada compiler supports OSX deployment target flag - yes
-- Detecting Ada compiler ABI info
-- Detecting Ada compiler ABI info - done
-- Check for working Ada compiler: /usr/local/opt/GNAT/2020/bin/gnat - skipped
-- Detecting Ada compile features
-- Detecting Ada compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: .../build

and the compilation:

[ 50%] Building Ada object CMakeFiles/ada_test.dir/hello.o
/usr/local/opt/GNAT/2020/bin/gnat make -c -u -D CMakeFiles/ada_test.dir .../hello.adb -cargs   -isysroot /Applications/ -gnat2012
gcc -c -I/Users/marc/tests/cmake/ -isysroot /Applications/ -gnat2012 -I- -o .../build/CMakeFiles/ada_test.dir/hello.o .../hello.adb
[100%] Linking Ada executable ada_test
/usr/local/opt/GNAT/2020/bin/gnat make -b -l -o ada_test hello -aOCMakeFiles/ada_test.dir -cargs  -isysroot /Applications/ -largs
gnatbind -aOCMakeFiles/ada_test.dir -x .../build/CMakeFiles/ada_test.dir/hello.ali
gnatlink .../build/CMakeFiles/ada_test.dir/hello.ali -o ada_test
[100%] Built target ada_test

1 Like

Excellent! That did the trick, thanks!