Hello,
I have scoured through this until I almost went blind.
https://cmake.org/cmake/help/latest/module/FetchContent.html
Have the following section in a cmake file because I need a much newer version of libtool libraries than Ubuntu 18.04 has.
if (CMAKE_SYSTEM_NAME MATCHES “(Linux|OpenBSD|FreeBSD|NetBSD|DragonFly)”)
# CMake is an odd duck. If you provide SOURCE_DIR definition for
# external project, PREFIX will not create the other directories.
# CMake ASS-U-ME-s all external projects are CMAKE builds. Not
# the case with libtool and so many other things.
#
# The hacky looking path for the configure command is a result of
# CMake forcing its own directory structure on external project.
#
include(ExternalProject)
include(FetchContent)
FetchContent_Populate(
ls_libtool
SUBBUILD_DIR "${CMAKE_BINARY_DIR}/ls_libtool"
URL https://ftp.gnu.org/gnu/libtool/libtool-2.5.4.tar.gz
DOWNLOAD_NO_PROGRESS ON
DOWNLOAD_EXTRACT_TIMESTAMP false
CONFIGURE_COMMAND ${CMAKE_BINARY_DIR}/ls_libtool/src/ls_libtool/configure --prefix=${LIBTOOL_INSTALL_PREFIX} "CFLAGS=-g -O0 ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}}"
BUILD_COMMAND make
INSTALL_COMMAND make install
)
message( "*******ls_libtool_SOURCE_DIR: ${ls_libtool_SOURCE_DIR}")
message( "*******ls_libtool_BINARY_DIR: ${ls_libtool_BINARY_DIR}")
target_link_libraries(LsCsCore PUBLIC ${LIBTOOL_INSTALL_PREFIX}/lib/libltdl)
target_include_directories(LsCsCore
PUBLIC
$<BUILD_INTERFACE:${LIBTOOL_INSTALL_PREFIX}/include>
$<INSTALL_INTERFACE:include>)
endif()
Just to round out the environment
developer@developer-U1804-VirtualBox:~/github_projects/ls-cs$ cmake --version
cmake version 4.2.3
CMake suite maintained and supported by Kitware (kitware.com/cmake).
When this executes (for lack of a better term) I get the following:
– Build files have been written to: /home/developer/github_projects/LsCs_local_build/ls_libtool
[1/9] Creating directories for ‘ls_libtool-populate’
[1/9] Performing download step (download, verify and extract) for ‘ls_libtool-populate’
– Downloading…
dst=‘/home/developer/github_projects/LsCs_local_build/ls_libtool/ls_libtool-populate-prefix/src/libtool-2.5.4.tar.gz’
timeout=‘none’
inactivity timeout=‘none’
– Using src=‘https://ftp.gnu.org/gnu/libtool/libtool-2.5.4.tar.gz’
– Downloading… done
– extracting…
src=‘/home/developer/github_projects/LsCs_local_build/ls_libtool/ls_libtool-populate-prefix/src/libtool-2.5.4.tar.gz’
dst=‘/home/developer/github_projects/LsCs_local_build/src/core/ls_libtool-src’
– extracting… [tar xf]
– extracting… [analysis]
– extracting… [rename]
– extracting… [clean up]
– extracting… done
[2/9] No update step for ‘ls_libtool-populate’
[3/9] No patch step for ‘ls_libtool-populate’
[5/9] No configure step for ‘ls_libtool-populate’
[6/9] No build step for ‘ls_libtool-populate’
[7/9] No install step for ‘ls_libtool-populate’
[8/9] No test step for ‘ls_libtool-populate’
[9/9] Completed ‘ls_libtool-populate’
*******ls_libtool_SOURCE_DIR: /home/developer/github_projects/LsCs_local_build/src/core/ls_libtool-src
*******ls_libtool_BINARY_DIR: /home/developer/github_projects/LsCs_local_build/src/core/ls_libtool-build
Later on the build gags because
*** Building LSCS
ninja: error: ‘ls_libtool/install/lib/libltdl’, needed by ‘src/core/libLsCsCore.so.0.2.1’, missing and no known rule to make it
I put all of the information in that block required by externalproject to build and that will, you just cannot use the thing because the location of header files and built libraries does not exist during configuration.
All I want is for CMake to pull down this non-CMake project and build it so I can use the headers and libraries as part of my project. Bundling them up for deployment and all.
How do I make build and install steps for the populate? I cannot find anything on this.
Thanks in advance.
FetchContent_Populate() only populates content, and it is only meant to be used in CMake’s script mode now. If you want to add the populated content to your build, you should use FetchContent_MakeAvailable() instead. The start of the documentation for FetchContent_Populate() states this:
The FetchContent_Populate() command is a self-contained call which can be used to perform content population as an isolated operation. It is rarely the right command to use, projects should almost always useFetchContent_Declare() and FetchContent_MakeAvailable() instead. The main use case for FetchContent_Populate() is in CMake script mode as part of implementing some other higher level custom feature.
A bit further down in those docs, there’s this statement which explains why your use of CONFIGURE_COMMAND, BUILD_COMMAND, and INSTALL_COMMAND is inappropriate:
The following options are explicitly prohibited (they are disabled by the FetchContent_Populate() command):
CONFIGURE_COMMAND
BUILD_COMMAND
INSTALL_COMMAND
TEST_COMMAND
If you’re happy to have your ls_libtool dependency built as its own external project as a sub-build rather than as part of the main build, use ExternalProject_Add() instead of any of the FetchContent_... machinery. Since the ls_libtool dependency appears to be a non-CMake project, it isn’t really appropriate for the FetchContent use case.
Thanks Craig!
I forgot to come back and answer my own question. After intense slamming of head against keyboard and wall given libtool’s lack of documentation, I did find the solution. There really is only one way to do it.
CMake is an odd duck. If you provide SOURCE_DIR definition for
external project, PREFIX will not create the other directories.
CMake ASS-U-ME-s all external projects are CMAKE builds. Not
the case with libtool and so many other things.
The hacky looking path for the configure command is a result of
CMake forcing its own directory structure on external project.
include(ExternalProject)
set(LS_LIBTOOL_BYPRODUCTS
“${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.a”
“${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.la”
“${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.so”
“${LIBTOOL_INSTALL_PREFIX}/include/ltdl.h”
“${LIBTOOL_INSTALL_PREFIX}/include/libltdl/lt_dlloader.h”
“${LIBTOOL_INSTALL_PREFIX}/include/libltdl/lt_error.h”
“${LIBTOOL_INSTALL_PREFIX}/include/libltdl/lt_system.h”
)
NOTE: If you change the file here you may need to change the libldtl install version.
Must provide BUILD_BYPRODUCTS when using ninja-build
ExternalProject_Add(
ls_libtool
PREFIX “${CMAKE_BINARY_DIR}/ls_libtool”
DOWNLOAD_DIR “${CMAKE_BINARY_DIR}”
URL https://ftp.gnu.org/gnu/libtool/libtool-2.5.4.tar.gz
DOWNLOAD_NO_PROGRESS ON
DOWNLOAD_EXTRACT_TIMESTAMP false
UPDATE_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_SOURCE_DIR}/libtool-configure.ac
${CMAKE_BINARY_DIR}/ls_libtool/src/ls_libtool/configure.ac
CONFIGURE_COMMAND ${CMAKE_BINARY_DIR}/ls_libtool/src/ls_libtool/configure --prefix=${LIBTOOL_INSTALL_PREFIX} "CFLAGS=-g -O0" "CXXFLAGS=-g -O0"
BUILD_COMMAND make
BUILD_BYPRODUCTS ${LS_LIBTOOL_BYPRODUCTS}
)
BUILD_BYPRODUCTS is extremely important. Very little documentation on it, but if you are using ninja with CMake, nothing works without it. Theoretically CMake would deploy these according to the doc, it don’t happen.
libtool headers and libraries
install(
FILES
${LIBTOOL_INSTALL_PREFIX}/include/ltdl.h
DESTINATION ${LSCS_INST_INCLUDE}
COMPONENT Development
)
install(
FILES
${LIBTOOL_INSTALL_PREFIX}/include/libltdl/lt_dlloader.h
${LIBTOOL_INSTALL_PREFIX}/include/libltdl/lt_error.h
${LIBTOOL_INSTALL_PREFIX}/include/libltdl/lt_system.h
DESTINATION ${LSCS_INST_INCLUDE}
COMPONENT Development
)
NOTE:: Need dynamic way of determining major version of library or a for loop finding each
This hard coding bad.
install(
FILES
${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.a
${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.la
${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.so
${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.so.7
${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.so.7.3.3
DESTINATION ${LSCS_INST_LIB}
COMPONENT Development
COMPONENT Runtime
)
To finish out the discussion
if (CMAKE_SYSTEM_NAME MATCHES “(Linux|OpenBSD|FreeBSD|NetBSD|DragonFly)”)
add_library(ls_libtool_ep SHARED IMPORTED GLOBAL)
add_dependencies(ls_libtool_ep ls_libtool)
set_target_properties(ls_libtool_ep PROPERTIES IMPORTED_LOCATION "${LIBTOOL_INSTALL_PREFIX}/lib/libltdl.so")
include_directories( "${LIBTOOL_INSTALL_PREFIX}/include" )
add_dependencies(LsCsCore ls_libtool)
target_link_libraries(LsCsCore PRIVATE ls_libtool_ep)
That’s how you both make libtools available to your project and control the build order.
I do thank you for your feedback. It reminded me to come back here and document the solution.