How to copy directory from source tree to binary tree? - c

Copying directory from source tree to binary tree. For example: How to copy www to bin folder.
work
├─bin
└─src
├─doing
│ └─www
├─include
└─lib
Thanks.

Since version 2.8, the file command has a COPY sub-command:
file(COPY yourDir DESTINATION yourDestination)
Note that:
Relative input paths are evaluated with respect to the current source
directory, and a relative destination is evaluated with respect to the
current build directory

With CMake 2.8 or later, use the file(COPY ...) command.
With CMake versions below 2.8, the following macro copies files from one directory to another. If you don't want to substitute variables in the copied files, then change the configure_file #ONLY argument (for example to COPYONLY).
# Copy files from source directory to destination directory, substituting any
# variables. Create destination directory if it does not exist.
macro(configure_files srcDir destDir)
message(STATUS "Configuring directory ${destDir}")
make_directory(${destDir})
file(GLOB templateFiles RELATIVE ${srcDir} "${srcDir}/*")
foreach(templateFile ${templateFiles})
set(srcTemplatePath ${srcDir}/${templateFile})
if(NOT IS_DIRECTORY ${srcTemplatePath})
message(STATUS "Configuring file ${templateFile}")
configure_file(
${srcTemplatePath}
${destDir}/${templateFile}
#ONLY)
endif(NOT IS_DIRECTORY ${srcTemplatePath})
endforeach(templateFile)
endmacro(configure_files)

As nobody has mentioned cmake -E copy_directory as a custom target, here's what I've used:
add_custom_target(copy-runtime-files ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/runtime-files-dir ${CMAKE_BINARY_DIR}/runtime-files-dir
DEPENDS ${MY_TARGET})

The configure command will only copy files when cmake is run. Another option is to create a new target, and use the custom_command option. Here's one that I use (if you run it more than once, you'll have to modify the add_custom_target line to make it unique for each call).
macro(copy_files GLOBPAT DESTINATION)
file(GLOB COPY_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${GLOBPAT})
add_custom_target(copy ALL
COMMENT "Copying files: ${GLOBPAT}")
foreach(FILENAME ${COPY_FILES})
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
set(DST "${DESTINATION}/${FILENAME}")
add_custom_command(
TARGET copy
COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST}
)
endforeach(FILENAME)
endmacro(copy_files)

Use execute_process and call cmake -E. If you want a deep copy, you can use the copy_directory command. Even better, you could create a symlink (if your platform supports it) with the create_symlink command. The latter can be achieved like this:
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/path/to/www
${CMAKE_BINARY_DIR}/path/to/www)
From: http://www.cmake.org/pipermail/cmake/2009-March/028299.html

Thank! That is really helpful advice to use bunch of add_custom_target and add_custom_command. I wrote the following function to use everywhere in my projects. Is also specifies the installation rule. I use it primarily to export interface header files.
#
# export file: copy it to the build tree on every build invocation and add rule for installation
#
function (cm_export_file FILE DEST)
if (NOT TARGET export-files)
add_custom_target(export-files ALL COMMENT "Exporting files into build tree")
endif (NOT TARGET export-files)
get_filename_component(FILENAME "${FILE}" NAME)
add_custom_command(TARGET export-files COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${DEST}/${FILENAME}")
install(FILES "${FILE}" DESTINATION "${DEST}")
endfunction (cm_export_file)
Usage looks like this:
cm_export_file("API/someHeader0.hpp" "include/API/")
cm_export_file("API/someHeader1.hpp" "include/API/")

Based on the answer from Seth Johnson; wrote for more convenience:
# Copy files
macro(resource_files files)
foreach(file ${files})
message(STATUS "Copying resource ${file}")
file(COPY ${file} DESTINATION ${Work_Directory})
endforeach()
endmacro()
# Copy directories
macro(resource_dirs dirs)
foreach(dir ${dirs})
# Replace / at the end of the path (copy dir content VS copy dir)
string(REGEX REPLACE "/+$" "" dirclean "${dir}")
message(STATUS "Copying resource ${dirclean}")
file(COPY ${dirclean} DESTINATION ${Work_Directory})
endforeach()
endmacro()

Related

Equivalent of mkdir -p for cleartool mkdir

UNIX mkdir has the -p flag that creates the parent directories if they don't exist. Is there an equivalent in cleartool for that? Obviously cleartool mkdir foo/bar/ doens't work when foo doesn't already exist.
The simplest way is to create a file in the directory structure and use mkelem -mkpath...
I created a "temp1" directory, and a "temp2" directory, and a "temp.txt" file in one of my sandbox vobs, then added the file to source control with -mkpath from the parent of the "temp1" view private directory.
PS M:\tempview\foobarf\Documents> cleartool mkelem -mkpath .\temp1\temp2\temp.txt
Creating parent directory element ".\temp1\temp2".
Creating parent directory element ".\temp1".
Created directory element ".\temp1".
Checking out parent directory ".\temp1".
Created directory element ".\temp1\temp2".
Checking out parent directory ".\temp1\temp2".
Creation comments for ".\temp1\temp2\temp.txt":
Test1.
.
Created element ".\temp1\temp2\temp.txt" (type "utf16le_file").
Checked out ".\temp1\temp2\temp.txt" from version "\main\0".
It's UTF-16LE because Powershell's Locale is wide character and the "temp.txt" was created using "dir > temp1\temp2\temp.txt".
cleartool mkelem -mkpath is a good option when adding one file.
But if you have multiple files to add, in a tree structure which does not exist yet, don't forget about clearfsimport: it can import flat files to a branch in one command, and will create any missing folder for you.
As seen here: clearfsimport -rec -nset <Source> <target>

Coverity and "Failed to initialize ICU, try using the --prevent-root option"

I have the bin directory in the build directory of my project.
When I run the command ./bin/cov-build --dir cov-int make I get the following error -
[ERROR] Failed to initialize ICU, try using the --prevent-root option.
Coverity uses ICU to handle multibyte encodings. This requires the ICU data files, present in the Coverity installation. That error suggests those files are either missing or not present in the expected location, and suggests you try using --prevent-root to tell it where it can expect to find the files.
Did you only copy the bin directory to your project? This would likely explain the issue, and using --prevent-root to point to the actual Coverity installation should resolve it.
Dockerized version - Minimum packages
I have dockerized coverity. Considering the whole enterprise version install equates to 4.9GB, I could get away with coverity for python by trial-and-error by selecting the packages needed...
According to Docker's layers/caching rules, docker will write a layer after the execution of any instruction. For this reason, you can design the docker image with Multi-layers and select only the files needed.
After I copied the correct set of dirs, the error went away and I could execute cov-configure python...
Dockerfile
Incomplete source-code...
COPY --from=prepare-install /opt/coverity/analysis/bin /opt/coverity/analysis/bin
COPY --from=prepare-install /opt/coverity/analysis/bin/cov-* /opt/coverity/analysis/bin/
COPY --from=prepare-install /opt/coverity/analysis/config/parse_warnings.conf.sample /opt/coverity/analysis/config/parse_warnings.conf.sample
COPY --from=prepare-install /opt/coverity/analysis/config/user_nodefs.h /opt/coverity/analysis/config/user_nodefs.h
COPY --from=prepare-install /opt/coverity/analysis/config/wrapper_escape.conf /opt/coverity/analysis/config/wrapper_escape.conf
# ls /opt/coverity/analysis/config/templates/ | xargs -I {} echo "COPY --from=prepare-install /opt/coverity/analysis/config/templates/{} /opt/coverity/analysis/config/templates/{}"
COPY --from=prepare-install /opt/coverity/analysis/config/templates/python /opt/coverity/analysis/config/templates/python
# File doesn't exist: '/opt/coverity/analysis/config/templates/generic/generic_switches.dat'
COPY --from=prepare-install /opt/coverity/analysis/config/templates/generic /opt/coverity/analysis/config/templates/generic
COPY --from=prepare-install /opt/coverity/analysis/config/templates/generic_linker /opt/coverity/analysis/config/templates/generic_linker
COPY --from=prepare-install /opt/coverity/analysis/config/templates/xlc /opt/coverity/analysis/config/templates/xlc
# Addressing the error
# > [coverity-python 6/6] RUN cov-configure --python: No valid XML DTD catalog found, try using the --prevent-root option.
COPY --from=prepare-install /opt/coverity/analysis/certs /opt/coverity/analysis/certs
COPY --from=prepare-install /opt/coverity/analysis/dtd /opt/coverity/analysis/dtd
COPY --from=prepare-install /opt/coverity/analysis/xsl /opt/coverity/analysis/xsl
# Was failing with https://stackoverflow.com/questions/65184937/fatal-python-error-init-fs-encoding-failed-to-get-the-python-codec-of-the-file
# As it is configured with python3.9, not python3.7 as it is packaged
COPY --from=prepare-install /opt/coverity/analysis/lib/python3.9 /opt/coverity/analysis/lib/python3.9
...
...
Docker Image
```console
$ docker images | more
REPOSITORY TAG IMAGE ID SIZE
dockerhub.company.com/coverity/python:2022.6.0 605MB

How can I pull a specific file into the fileset?

I'm writing a library that makes use of a file from a GitHub repository that I don't own:
git init foo
cd foo
git submodule add https://github.com/KhronosGroup/Vulkan-Docs.git github/KhronosGroup/Vulkan-Docs
mkdir -p src/com/example/foo resources/com/example/foo
Here are the other two relevant files in foo.
build.boot:
(set-env!
:resource-paths #{"src" "resources"}
:dependencies '[[adzerk/bootlaces "0.1.13" :scope "test"]])
(require '[adzerk.bootlaces :refer :all])
(deftask run [f function SYM sym]
(with-pass-thru _
(require (symbol (namespace function)))
((resolve function))))
(def +version+ "0.1.0-SNAPSHOT")
(bootlaces! +version+ :dont-modify-paths? true)
(task-options!
pom {:project 'com.example/foo
:version +version+})
src/com/example/foo/core.clj:
(ns com.example.foo.core
(:require [clojure.java.io :as io]))
(defn bar []
(some-> "com/example/foo/spec.xml" io/resource slurp count prn))
What I want is some sort of add task that allows me to do something like this:
boot add --resource --from github/KhronosGroup/Vulkan-Docs/src/spec/vk.xml --to com/example/foo/spec.xml run -f com.example.foo.core/bar
585128
I tried using the -R option of sift, but it has two problems for my use case:
Far more files than just the one I want (vk.xml) are pulled into the fileset, which would bloat the size of my JAR
Because -R simply adds the directory to the set of resource paths, all of its contents are added to the fileset at the top level, which could easily clobber my own resources
Essentially, I want something that has the same effect as the below three commands, but without actually touching the resources directory:
cp github/KhronosGroup/Vulkan-Docs/src/spec/vk.xml resources/com/example/foo/spec.xml
boot build-jar
rm resources/com/example/foo/spec.xml
In other words, the com.example/foo JAR should contain that XML file as a resource, so that resource should be available when I use com.example/foo from another project:
boot -d com.example/foo:0.1.0-SNAPSHOT repl
(require '[com.example.foo.core :as foo])
;;=> nil
(foo/bar)
;; 585128
;;=> nil
How can I pull a specific file (e.g. from a Git submodule) into the fileset at a specific location as a resource, without touching any of the files that I already have in the fileset?

Compare strings inside in the two different directories using array

I don't get the scenario of this given code. All I wanted is to compare the files that is given below. But, in this script nothings happen. I assume that this given code can executed wherever like in /root and it will run. Please check this out.
#!/bin/bash
for file in /var/files/sub/old/*
do
# Strip path from file name
file="${file##*/}"
# Strip everything after the first hyphen
prefix="${file%%-*}-"
# Strip everything before the second-to-last dot
suffix="$(echo $file | awk -F. '{ print "."$(NF-1)"."$NF }')"
# Create new file name from $prefix and $suffix, and any version number
new=$(echo "/var/files/new/${prefix}"*"${suffix}")
# If file exists in the 'new' folder:
if test -f "${new}"
then
# Do string comparison to see if new file is lexicographically "greater than" old
if [[ "${new##*/}" > "${file}" ]]
then
# If so, delete the old version.
rm /var/sub/files/old/"${file}"
else
# 'new' file is NOT newer, delete it instead.
rm "${new}"
fi
fi
done
# Move all new files into the old folder.
mv /var/files/new/* /var/files/sub/old/
Example files inside of each sub- directories ..
/var/files/sub/old/
firefox-24.5.0-1.el5_10.i386.rpm
firefox-24.5.0-1.el5_10.x86_64.rpm
google-1.6.0-openjdk-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
google-1.6.0-openjdk-demo-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
/var/files/new/
firefox-25.5.0-1.el5_10.i386.rpm
firefox-25.5.0-1.el5_10.x86_64.rpm
ie-1.6.0-openjdk-devel-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
ie-1.6.0-openjdk-javadoc-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
ie-1.6.0-openjdk-src-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
google-2.6.0-openjdk-demo-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
In this instance, I want to get the files that are the same. So the files that are the same in the given example are:
firefox-24.5.0-1.el5_10.i386.rpm
firefox-24.5.0-1.el5_10.x86_64.rpm
google-1.6.0-openjdk-demo-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
in the old/ directory and for the new/ directory the equivalents are:
firefox-25.5.0-1.el5_10.i386.rpm
firefox-25.5.0-1.el5_10.x86_64.rpm
google-2.6.0-openjdk-demo-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
The files have similarity for their first characters. It will display in the terminal. After that, there will be another comparing again of the files and the comparison is about which file is more updated one by the number after the name of the file like: firefox-24.5.0-1.el5_10.i386.rpm compared with firefox-25.5.0-1.el5_10.i386.rpm. So in that instance the firefox-24.5.0-1.el5_10.i386.rpm will be replaced by firefox-25.5.0-1.el5_10.i386.rpm because it has a greater value and more updated one and same as other files that are similar. And if the old one is removed and the new will take replacement of it.
So at this moment after the script has been executed the output will be like this.
/var/files/sub/old/
google-1.6.0-openjdk-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
firefox-25.5.0-1.el5_10.i386.rpm
firefox-25.5.0-1.el5_10.x86_64.rpm
ie-1.6.0-openjdk-devel-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
ie-1.6.0-openjdk-javadoc-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
ie-1.6.0-openjdk-src-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
google-2.6.0-openjdk-demo-1.6.0.0-5.1.13.3.el5_10.x86_64.rpm
/var/files/new/
<<empty all files here must to moved to other directory take as a replacement>>
Can anyone help me to make a script for this ? above is just an example. Let's assume that there are lots of files to considered as similar and need to removed and moved.
You can use rpm to get the name of the package without version or architecture strings:
rpm -qi -p /firefox-25.5.0-1.el5_10.i386.rpm
Gives:
Name : firefox
Version : 25.5.0
Release : 1.el5_10
Architecture: i386
....
So you can compare the Names to find related packages.
If the goal here is to have the newrpms directory have only the newest version of each RPM from a combination of sources then you most likely want to simply combine all the files in a single directory and then use the repomanage tool (from the yum-utils package, at least on CentOS) to have it inform you which of the RPMS are old and remove them.
Something like:
repomanage --old combined_rpms_directory | xargs -r rm
As to your initial script
for i in $(\ls -d ./new/*);
do
diff ${i} newrpms/;
rm ${i}
done
You generally don't want to "parse" the output from ls, especially when a glob will do what you want just as easily (for i in ./new/* in this case).
diff ${i} newrpms/ is attempting to diff a file and a directory (or two directories if your ls/glob happened to catch a directory) but in neither case will diff do what you want there. That being said what diff does doesn't really matter because, as Barmar said in his comment
your script is removing them without testing the result of diff
A bash script that does the checking. Here's how it works:
Traverse over each file in the old files directory. Get the prefix (package name with no version, architecture, etc), eg. firefox-; get the suffix (architecture.rpm), eg. .i386.rpm.
Attempt to match prefix and suffix with any version number within the new files directory, ie. firefox-*.i386.rpm. If there is a match, $new will contain the file name, eg. firefox-25.5.0-1.el5_10.i386.rpm; if no match, $new will equal the literal string firefox-*.i386.rpm which is not a file.
Check new files directory for existence of $new.
If it exists, check that $new is indeed newer than the old version. This is done by lexicographical string comparison, ie. firefox-24.5.0-1.el5_10.i386.rpm is less than firefox-25.5.0-1.el5_10.i386.rpm because it comes earlier in the alphabet. Conveniently, sane versioning schemes also happen to be alphabetical. NB: this may fail, for example, when comparing version 2 to version 10.
A new version of a file in the old files directory has been found! In this case, get rid of the old file with rm. If the file in the new directory is not newer, then delete it instead.
Done removing old versions. Old files directory has only files without newer versions.
Move all new files into old directory, leaving newest files in old directory, and new directory empty.
#!/bin/bash
for file in /var/files/sub/old/*
do
# Strip path from file name
file="${file##*/}"
# Strip everything after the first hyphen
prefix="${file%%-*}-"
# Strip everything before the second-to-last dot
suffix="$(echo $file | awk -F. '{ print "."$(NF-1)"."$NF }')"
# Create new file name from $prefix and $suffix, and any version number
new=$(echo "/var/files/new/${prefix}"*"${suffix}")
# If file exists in the 'new' folder:
if test -f "${new}"
then
# Do string comparison to see if new file is lexicographically "greater than" old
if [[ "${new##*/}" > "${file}" ]]
then
# If so, delete the old version.
rm /var/sub/files/old/"${file}"
else
# 'new' file is NOT newer, delete it instead.
rm "${new}"
fi
fi
done
# Move all new files into the old folder.
mv /var/files/new/* /var/files/sub/old/

cmake: check if file exists at build time rather than during cmake configuration

I have a custom build command that needs to check if a certain file exists. I tried using
IF(EXISTS "/the/file")
...
ELSE()
...
ENDIF()
but that test is only evaluated one; when cmake is first run. I need it to perform the test every time a make is done. What's the method to check at make-time? Thanks.
You can use add_custom_command to invoke CMake itself in script mode by using the -P command line option.
So your command would be something like:
set(FileToCheck "/the/file")
add_custom_command(TARGET MyExe
POST_BUILD
COMMAND ${CMAKE_COMMAND}
-DFileToCheck=${FileToCheck}
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
COMMENT "Checking if ${FileToCheck} exists...")
and your script file "check.cmake" would be something like:
if(EXISTS ${FileToCheck})
message("${FileToCheck} exists.")
else()
message("${FileToCheck} doesn't exist.")
endif()
A similar idea
You're going to need add_custom_command, but if you're willing to be a little Unix specific you can always use test.
set(FileToCheck "/the/file")
add_custom_command( OUTPUT output.txt
COMMAND test -e output.txt || echo "Do something meaningful"
COMMENT "Checking if ${FileToCheck} exists...")
[#Frazers] answer is great if you need to add custom logic inside the if(EXISTS).
However, if you just need your build to fail if a single file is missing you can use the cmake -E command line mode to compare the file with itself.
This will make sure the build always stops if the provided file doesn't exist, it's cross-platform safe and works in every version of cmake since 3.0.
set(_fileToCheck "foo.txt")
add_custom_command(TARGET YourTarget
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E compare_files ${_fileToCheck} ${_fileToCheck}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Checking if ${_fileToCheck} exists, build will fail if it doesn't"
)

Resources