Skip to content

Commit

Permalink
Break out the cmakefiles and distclean functions
Browse files Browse the repository at this point in the history
These functions (for identifying source files and build outputs
respectively) aren't actually specific to BRL-CAD - break them out into
their own file to make it easier to (potentially) reuse them in an
external 3rd party repository.
  • Loading branch information
starseeker committed Aug 2, 2023
1 parent 3e64c88 commit 7848a47
Show file tree
Hide file tree
Showing 4 changed files with 294 additions and 161 deletions.
43 changes: 43 additions & 0 deletions misc/CMake/BRLCAD_Targets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,49 @@ function(BRLCAD_ADDLIB libname srcslist libslist)

endfunction(BRLCAD_ADDLIB libname srcslist libslist)


#-----------------------------------------------------------------------------
# We need a way to tell whether one path is a subpath of another path without
# relying on regular expressions, since file paths may have characters in them
# that will trigger regex matching behavior when we don't want it. (To test,
# for example, use a build directory name of build++)
#
# Sets ${result_var} to 1 if the candidate subpath is actually a subpath of
# the supplied "full" path, otherwise sets it to 0.
#
# The routine below does the check without using regex matching, in order to
# handle path names that contain characters that would be interpreted as active
# in a regex string.
if (NOT COMMAND IS_SUBPATH)
function(IS_SUBPATH candidate_subpath full_path result_var)

# Just assume it isn't until we prove it is
set(${result_var} 0 PARENT_SCOPE)

# get the CMake form of the path so we have something consistent to work on
file(TO_CMAKE_PATH "${full_path}" c_full_path)
file(TO_CMAKE_PATH "${candidate_subpath}" c_candidate_subpath)

# check the string lengths - if the "subpath" is longer than the full path,
# there's not point in going further
string(LENGTH "${c_full_path}" FULL_LENGTH)
string(LENGTH "${c_candidate_subpath}" SUB_LENGTH)
if("${SUB_LENGTH}" GREATER "${FULL_LENGTH}")
return()
endif("${SUB_LENGTH}" GREATER "${FULL_LENGTH}")

# OK, maybe it's a subpath - time to actually check
string(SUBSTRING "${c_full_path}" 0 ${SUB_LENGTH} c_full_subpath)
if(NOT "${c_full_subpath}" STREQUAL "${c_candidate_subpath}")
return()
endif(NOT "${c_full_subpath}" STREQUAL "${c_candidate_subpath}")

# If we get here, it's a subpath
set(${result_var} 1 PARENT_SCOPE)

endfunction(IS_SUBPATH)
endif (NOT COMMAND IS_SUBPATH)

#---------------------------------------------------------------------
# For situations when a local 3rd party library (say, zlib) has been
# chosen in preference to a system version of that library, it is
Expand Down
165 changes: 4 additions & 161 deletions misc/CMake/BRLCAD_Util.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
# Need sophisticated option parsing
include(CMakeParseArguments)

# CMAKEFILES and DISTCLEAN (and supporting routines) are defined
# in TrackFiles
include(TrackFiles)

#-----------------------------------------------------------------------------
# Find the executable extension, if there is one. Really should be able to use
# CMAKE_EXECUTABLE_SUFFIX for this, but we've hit a few cases over the years
Expand All @@ -45,24 +49,6 @@ include(CMakeParseArguments)
# with the platform exe extension, if there is one.
get_filename_component(EXE_EXT "${CMAKE_COMMAND}" EXT)

#-----------------------------------------------------------------------------
# We want to support a "distclean" build target that will clear all
# CMake-generated files from a source directory in the case of an
# in-source-dir configuration. Not recommended, but we'll try to
# recover if it happens.
define_property(GLOBAL PROPERTY CMAKE_DISTCLEAN_TARGET_LIST BRIEF_DOCS "All CMake generated files" FULL_DOCS "List of all files generated by CMake")
function(distclean)
foreach(item ${ARGN})
get_filename_component(item_dir ${item} DIRECTORY)
if ("${item_dir}" STREQUAL "")
set(item_path "${CMAKE_CURRENT_BINARY_DIR}/${item}")
else ("${item_dir}" STREQUAL "")
set(item_path "${item}")
endif ("${item_dir}" STREQUAL "")
set_property(GLOBAL APPEND PROPERTY CMAKE_DISTCLEAN_TARGET_LIST "${item_path}")
endforeach(item ${ARGN})
endfunction(distclean)

#-----------------------------------------------------------------------------
# Use a variation on Fraser's approach for capturing command line args from
# http://stackoverflow.com/questions/10205986/how-to-capture-cmake-command-line-arguments
Expand Down Expand Up @@ -128,46 +114,6 @@ function(BOX_PRINT input_string border_string)
message("${SEPARATOR_STRING}")
endfunction()

#-----------------------------------------------------------------------------
# We need a way to tell whether one path is a subpath of another path without
# relying on regular expressions, since file paths may have characters in them
# that will trigger regex matching behavior when we don't want it. (To test,
# for example, use a build directory name of build++)
#
# Sets ${result_var} to 1 if the candidate subpath is actually a subpath of
# the supplied "full" path, otherwise sets it to 0.
#
# The routine below does the check without using regex matching, in order to
# handle path names that contain characters that would be interpreted as active
# in a regex string.
function(IS_SUBPATH candidate_subpath full_path result_var)

# Just assume it isn't until we prove it is
set(${result_var} 0 PARENT_SCOPE)

# get the CMake form of the path so we have something consistent to work on
file(TO_CMAKE_PATH "${full_path}" c_full_path)
file(TO_CMAKE_PATH "${candidate_subpath}" c_candidate_subpath)

# check the string lengths - if the "subpath" is longer than the full path,
# there's not point in going further
string(LENGTH "${c_full_path}" FULL_LENGTH)
string(LENGTH "${c_candidate_subpath}" SUB_LENGTH)
if("${SUB_LENGTH}" GREATER "${FULL_LENGTH}")
return()
endif("${SUB_LENGTH}" GREATER "${FULL_LENGTH}")

# OK, maybe it's a subpath - time to actually check
string(SUBSTRING "${c_full_path}" 0 ${SUB_LENGTH} c_full_subpath)
if(NOT "${c_full_subpath}" STREQUAL "${c_candidate_subpath}")
return()
endif(NOT "${c_full_subpath}" STREQUAL "${c_candidate_subpath}")

# If we get here, it's a subpath
set(${result_var} 1 PARENT_SCOPE)

endfunction(IS_SUBPATH)

#-----------------------------------------------------------------------------
# Plugins for libraries need a specific override of their output directories
# to put them in the correct relative location
Expand Down Expand Up @@ -200,109 +146,6 @@ function(PLUGIN_SETUP plugin_targets subdir)
endfunction(PLUGIN_SETUP)

#-----------------------------------------------------------------------------
# Distcheck needs to know what files are "supposed" to be present in order to
# make sure the source tree is clean prior to building a distribution tarball,
#
# For this set of functions to work correctly, it is important that any call
# (via target definitions or via explicit calls to CMAKEFILES) supply relative
# paths for files present in the source tree. Generated files fed into
# compilation targets are not one of the things that should be in lists
# generated by this function, and the only way to reliably recognize them is to
# reject files specified using their full path. Such files must use their full
# path in the build logic in order for out-of-src-dir builds to function, so as
# long as no full paths are used for files actually IN the source tree this
# method is reliable. The filtering logic will try to catch improperly
# specified files, but if the build directory and the source directory are one
# and the same this will not be possible.

define_property(GLOBAL PROPERTY CMAKE_IGNORE_FILES BRIEF_DOCS "distcheck ignore files" FULL_DOCS "List of files known to CMake")
define_property(GLOBAL PROPERTY CMAKE_IGNORE_DIRS BRIEF_DOCS "distcheck ignore dirs" FULL_DOCS "List of directories marked as fully known to CMake")

# If the build directory is not the same as the source directory, we can
# enforce the convention that only generated files be specified with their full
# name.
function(CHECK_SOURCE_DIR_FULLPATH ITEM_PATH)

# We can only do this if BINARY_DIR != SOURCE_DIR
if(NOT "${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
return()
endif(NOT "${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")

# If it's a full path in the binary dir, it's fine
IS_SUBPATH("${CMAKE_BINARY_DIR}" "${ITEM_PATH}" SUBPATH_TEST)
if(NOT "${SUBPATH_TEST}" STREQUAL "0")
return()
endif(NOT "${SUBPATH_TEST}" STREQUAL "0")

# If it's a full path in the source dir, it's fatal
IS_SUBPATH("${CMAKE_SOURCE_DIR}" "${ITEM_PATH}" SUBPATH_TEST)
if("${SUBPATH_TEST}" STREQUAL "1")
message(FATAL_ERROR "${ITEM} is listed in \"${CMAKE_CURRENT_SOURCE_DIR}\" using its absolute path. Please specify the location of this file using a relative path.")
endif("${SUBPATH_TEST}" STREQUAL "1")

endfunction(CHECK_SOURCE_DIR_FULLPATH ITEM_PATH)

function(CMFILE ITEM)

get_filename_component(ITEM_PATH "${ITEM}" PATH)
if(NOT "${ITEM_PATH}" STREQUAL "")
# The hard case - path specified, need some validation.
CHECK_SOURCE_DIR_FULLPATH("${ITEM_PATH}")

# Ignore files specified using full paths, since they
# should be generated files and are not part of the
# source code repository.
get_filename_component(ITEM_ABS_PATH "${ITEM_PATH}" ABSOLUTE)
if("${ITEM_PATH}" STREQUAL "${ITEM_ABS_PATH}")
return()
endif("${ITEM_PATH}" STREQUAL "${ITEM_ABS_PATH}")
endif(NOT "${ITEM_PATH}" STREQUAL "")

# Handle fatal cases
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${ITEM}")
message(FATAL_ERROR "Trying to ignore directory: ${CMAKE_CURRENT_SOURCE_DIR}/${ITEM}")
endif(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${ITEM}")
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${ITEM}")
message(FATAL_ERROR "Attempting to ignore non-existent file ${ITEM}, in directory \"${CMAKE_CURRENT_SOURCE_DIR}\"")
endif(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${ITEM}")

# We're good - log it
get_filename_component(item_absolute "${CMAKE_CURRENT_SOURCE_DIR}/${ITEM}" ABSOLUTE)
set_property(GLOBAL APPEND PROPERTY CMAKE_IGNORE_FILES "${item_absolute}")

endfunction(CMFILE ITEM)

function(CMAKEFILES)
if(NOT BRLCAD_IS_SUBBUILD)

# CMake flags to add_library/add_executable aren't going to be valid filenames - just
# yank them up front.
set(ITEMS ${ARGN})
if (NOT ITEMS)
return()
endif (NOT ITEMS)
list(REMOVE_ITEM ITEMS SHARED STATIC OBJECT WIN32 UNKNOWN IMPORTED MODULE INTERFACE EXCLUDE_FROM_ALL)
list(FILTER ITEMS EXCLUDE REGEX "TARGET_OBJECTS")

foreach(ITEM ${ITEMS})
CMFILE("${ITEM}")
endforeach(ITEM ${ITEMS})

endif(NOT BRLCAD_IS_SUBBUILD)
endfunction(CMAKEFILES FILESLIST)

# Routine to tell distcheck to ignore a series of items in a directory.
# Primarily useful when working with src/other dist lists.
function(CMAKEFILES_IN_DIR filestoignore targetdir)
if(NOT BRLCAD_IS_SUBBUILD)
set(CMAKE_IGNORE_LIST "")
foreach(filepath ${${filestoignore}})
set(CMAKE_IGNORE_LIST ${CMAKE_IGNORE_LIST} "${targetdir}/${filepath}")
endforeach(filepath ${filestoignore})
CMAKEFILES(${CMAKE_IGNORE_LIST})
endif(NOT BRLCAD_IS_SUBBUILD)
endfunction(CMAKEFILES_IN_DIR)

# configure a header for substitution and installation given a header
# template and an installation directory.
function(BUILD_CFG_HDR chdr targetdir)
Expand Down
1 change: 1 addition & 0 deletions misc/CMake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ set(cmake_ignore_files
RPath_Setup.cmake
ResetCache.cmake
TCL_PKGINDEX.cmake
TrackFiles.cmake
compat/README
compat/README.compat
compat/README.compat.c99
Expand Down
Loading

0 comments on commit 7848a47

Please sign in to comment.