[CMake] static library from several subdirectories

Michael Wild themiwi at gmail.com
Fri Mar 19 09:11:28 EDT 2010


Hi

I added my comments below, inline in the code


On 19. Mar, 2010, at 13:58 , Verweij, Arjen wrote:

> Hi,
> 
>> -----Original Message-----
>> From: Michael Wild [mailto:themiwi at gmail.com]
> 
> 
>> I'd recommend to change the add_sources function to do all the
>> preprocessing and then only add the products (.f, .f90, .c etc.) files
>> to the list. You can do the preprocessing like this (of course, you'll
>> have to change things for your setup, perhaps even do different things
>> depending on filename extension etc.)
>> 
>> find_program(FPP_EXECUTABLE fpp)
>> if(NOT FPP_EXECUTABLE)
>> message(SEND_ERROR "Failed to find fpp")
>> endif()
>> 
>> set(SRCS)
>> foreach(src IN LISTS ARGN)
>> get_filename_component(abs_src "${src}" ABSOLUTE)
>> file(RELATIVE_PATH rel_src "${CMAKE_CURRENT_SOURCE_DIR}" "${abs_src}")
>> set(pre "${CMAKE_CURRENT_BINARY_DIR}/${rel_src}")
>> add_custom_command(OUTPUT "${pre}"
>>   COMMAND ${FPP_EXECUTABLE} "${abs_src}" -o "${pre}"
>>   WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
>>   COMMENT "Creating ${pre}"
>>   VERBATIM
>>   )
>> list(APPEND SRCS "${pre}")
>> endforeach()
>> set_property(GLOBAL APPEND PROPERTY "${target}_SRCS" "${SRCS}")
> 
> OK, so I finally found some time to implement AND email the results. I tried it a little differently, then I tried Michael's approach. Both seem to fail, since at the moment I call add_library() my source file is unavailable. I hoped it would resolve the source file to a dependency through the custom command, but it doesn't and I can't get cmake to execute the conversion inline.
> 
> What am I missing? I'm trying again with my simple a/liba.c and b/b/libb.c setup, but this time I start out with liba.cr and libb.cr that need to be converted to liba.c and libb.c.
> 
> function(add_sources target)
>  # define the <target>_SRCS properties if necessary
>  get_property(prop_defined GLOBAL PROPERTY ${target}_SRCS DEFINED)
>  if(NOT prop_defined)
>    define_property(GLOBAL PROPERTY ${target}_SRCS
>      BRIEF_DOCS "Sources for the ${target} target"
>      FULL_DOCS "List of source files for the ${target} target")
>  endif()
>  # create list of sources (absolute paths)
>  set(SRCS)
>  foreach(src IN LISTS ARGN)

I know I used this syntax, but it is relatively new. Please check that it is supported by the CMake version you use...

>    string (REGEX REPLACE "^(.+)\\.cr$" "\\1" BASECR ${src} )
>    string (COMPARE EQUAL ${src} ${BASECR}.cr FILE_IS_C)

You're removing .cr from the file and then add it back again and compare it with the original name? that should always be TRUE, right?

>    if(NOT IS_ABSOLUTE "${src}")
>      get_filename_component(path_to_src "${src}" ABSOLUTE )
>      get_filename_component(path_to_src "${path_to_src}" PATH )
>      get_filename_component(src "${src}" ABSOLUTE)
>    endif()

This is dangerous, because if src is originally absolute, path_to_src will be undefined! Change it to this:

if(NOT IS_ABSOLUTE "${src}")
  get_filename_component(src "${src}" ABSOLUTE)
endif()
get_filename_component(path_to_src "${src}" PATH)

> 
>    add_custom_command(
>      OUTPUT "${path_to_src}/${BASECR}.c"
>      COMMAND cat "${path_to_src}/${BASECR}.cr" > "${path_to_src}/${BASECR}.c"
>      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
>      COMMENT "Creating ${path_to_src}/${BASECR}.c"
>      VERBATIM
>      )

You should NEVER write to the source directory. Don't even think about it. And output-redirection doesn't work. So for your test-purposes, you could try:

file(RELATIVE_PATH rel_path_to_src "${CMAKE_CURRENT_SOURCE_DIR}" "${path_to_src}")
set(out_file "${CMAKE_CURRENT_BINARY_DIR}/${rel_path_to_src}/${BASECR}.c")
add_custom_command(
  OUTPUT "${out_file}"
  COMMAND ${CMAKE_COMMAND} -E copy "${src}" "${out_file}"
  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
  COMMENT "Creating ${out_file}"
  VERBATIM
  )

> 
>    #add_custom_command (
>    #  OUTPUT ${path_to_src}/${BASECR}.c
>    #  COMMAND cat ${path_to_src}/${BASECR}.cr > ${path_to_src}/${BASECR}.c
>    #  DEPENDS ${path_to_src}/${BASECR}.cr
>    #  )
>    list(APPEND SRCS "${path_to_src}/${BASECR}.c")

Of course, change this then to

list(APPEND SRCS "${out_file}")

>  endforeach()
>  # append to global property
>  set_property(GLOBAL APPEND PROPERTY "${target}_SRCS" "${SRCS}")
> endfunction()
> 


You have to call ADD_SOURCES for all your sources BEFORE you do the ADD_LIBRARY call.

HTH

Michael



More information about the CMake mailing list