Reusing Custom Makefile for Static Library with Cmake

Reusing custom makefile for static library with cmake

You could also use imported targets and a custom target like this:

# set the output destination
set(SCINTILLA_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/scintilla/gtk/scintilla.a)
# create a custom target called build_scintilla that is part of ALL
# and will run each time you type make
add_custom_target(build_scintilla ALL
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scintilla/gtk
COMMENT "Original scintilla makefile target")

# now create an imported static target
add_library(scintilla STATIC IMPORTED)
# Import target "scintilla" for configuration ""
set_property(TARGET scintilla APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(scintilla PROPERTIES
IMPORTED_LOCATION_NOCONFIG "${SCINTILLA_LIBRARY}")

# now you can use scintilla as if it were a regular cmake built target in your project
add_dependencies(scintilla build_scintilla)

add_executable(foo foo.c)
target_link_libraries(foo scintilla)

# note, this will only work on linux/unix platforms, also it does building
# in the source tree which is also sort of bad style and keeps out of source
# builds from working.

How can I use CMake to merge my own .o files with a 3rd-party static library to create a new merged static library?

You can use add_custom_command to run libtool.

It takes several options, notably OUTPUT, which is the output file generated by the command, and DEPENDS, which is the list of dependencies the command requires to be ready when it is run.

You would specify OUTPUT as being the merged library (<my library>.a in your example), and DEPENDS as the object files being merged into the library (<my library's object files> in your example)

add_custom_command(
OUTPUT
${OUTPUT_LIB}

COMMAND
libtool --mode=link gcc -static -o ${OUTPUT_LIB} ${INPUT_OBJS} ${LIB_CUDA}

COMMENT
"Creating merged ${OUTPUT_LIB}"

DEPENDS
${INPUT_OBJS}
)

To then actually run the command you need to add a new target (in makefile parlance, this will create a phony target. In order to do this you use add_custom_target.

It takes several options, the ones we want are DEPENDS again, which we set to the output of the custom command, and ALL which adds it to the default ALL target.

add_custom_target(${OUTPUT_LIB}.create
ALL
DEPENDS
${OUTPUT_LIB}
)

CMake: reuse object files built for a lib into another lib target

You can use the new OBJECT library feature introduced in CMake 2.8.8. The idea is explained here. Basically, the OBJECT library is a similar concept to the convenience library known from Autotools to group object files.

Check the complete CMake OBJECT library tutorial.

CMake: How to reuse an object files for the tests subdirectory project?

What I normally do is that I separate the application logic into a static library (subdirectory), which is then used by both the main application and the tests.

You could keep it in a single dir as well, but then you still need to exclude the main.cpp when building the object library, because otherwise you will indeed have multiple definitions of main when building tests (as defined in both main.cpp and the test main).

If you are listing the files explicitly (which is highly recommended for CMake), you can simply omit the main.cpp from the list. If you use globbing to list the files, you can remove the file from the list as described here: How do I exclude a single file from a cmake `file(GLOB ... )` pattern?

How can I build two executables that share a main function in CMake?

You already have a src/CMakeLists.txt, so you are part of the way there. Put your overall build settings -- dependencies, C standard version, global compiler flags -- in the top-level CMakeLists.txt. In the subdirectories, put only your CMake commands for the executables, or whatever target makes sense locally.

(As an aside, define "enormous"? I've got top-level CMakeLists here that are anywhere between 200-950 lines, but I've seen 3000-line monstrosities as well)

Personally, from the minimal sketch of the source layout here, I'd do:

  • src/CMakeLists.txt does an add_subdirectory() command for each board, e.g. add_subdirectory(board/board_a) . If you like, set() a variable to a list of board names and you can iterate over it.
  • In each board's subdirectory, create a library -- shared, static, or OBJECT -- named after the board, with the sources for that board. For instance add_library(board_a OBJECT board.c)
  • Back in src/CMakeLists.txt again, for each board, add an executable with the source from app/ and link to the library defined for the board, like
    add_executable(exe_board_a app/source.c)
    target_link_library(exe_board_a PRIVATE board_a)
    If there are special considerations for that executable, set them there as well. Compile flags can be obtained from the library targets (use STATIC then, not OBJECT).

This moves most of the long-lists-of-sources and potentially compile flags to the per-board CMakeLists.txt and turns the intermediate level into a long list of "make this executable".

CMake can't link a custom library

Ok I solved it via adding:

target_link_libraries(custom_button PRIVATE raylib)

to the CMakeLists.txt

add_dependencies transitivity with add_subdirectory

The problem was with the add_library command. From the documentation

The target name has scope in the directory in which it is created and
below, but the GLOBAL option extends visibility.

So the solution was to add the GLOBAL option to the add_library command in the project/makefile_lib/CMakeLists.txt

add_custom_target(build_makefile_lib
ALL
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "makefile_lib makefile"
)

add_library(makefile_lib STATIC IMPORTED GLOBAL)
set_target_properties(makefile_lib
PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libmakefile_lib.a
)

add_dependencies(makefile_lib build_makefile_lib)

Edit: Note that this does not work for CMake versions <= 2.8.7 where the GLOBAL flag does not yet exist. See here for a possible workaround.

Using cmake with a custom file generator

The ADD_DEPENDENCIES command can only be used to add dependencies between top-level targets. The ADD_CUSTOM_COMMAND command however generates output files, but does not add new targets.

To make a custom target depend on generated files, use the DEPENDS options of the add_custom_target command:

set (LUA_COMPILED_FILES "")
foreach(F ${LUA_SCRIPT_FILES})
add_custom_command(
OUTPUT "${LUA_COMPILED_SCRIPTS}/${F}"
COMMAND ${LUAC} -o "${LUA_COMPILED_SCRIPTS}/${F}"
COMMENT "Compiling ${F} to binary")
list (APPEND LUA_COMPILED_FILES "${LUA_COMPILED_SCRIPTS}/${F}")
endforeach()

add_custom_target(LUABIND ALL DEPENDS ${LUA_COMPILED_FILES})


Related Topics



Leave a reply



Submit