Copy folder into subdirectory in CMake on Windows - windows

I have a CMake project using Makefiles on Windows, with a folder structure that looks like this (the build takes place in build):
project
|- build
|- ...
|- otherfolder
|- stuff
|- more stuff
As a build step (pre- or post doesn't matter), I want to make a copy of project into build (excluding the build folder), like so:
project
|- build
|- ...
|- project
|- otherfolder
|- stuff
|- more stuff
|- otherfolder
|- stuff
|- more stuff
Other options might be acceptable as well, e.g. copying to a temporary directory outside the project root before moving it into place, but CMake seemingly has no builtin support for generating temporary directories.
Things I've tried: xcopy has support for excluding certain files and directories, but refuses to copy even if I explicitly exclude the build folder. cmake -E copy_directory does not (from what I'm able to find) support excluding certain directories.
CMake's file(COPY ... PATTERN build EXCLUDE ... copies successfully, but it runs at CMake configure time and I haven't been able to find a way to make it run at build time.
I might resort to using Python and shutil, but it would be nice if it could be done without additional dependencies, so I'd prefer a batch file solution.

There are several ways for doing selectable directory copiing.
You can use cmake -P for execute cmake script at any time. E.g:
copy_to_build.cmake:
file(COPY . DESTINATION build PATTERN build EXCLUDE)
CMakeLists.txt:
add_custom_command(... COMMAND cmake -P copy_to_build.cmake)
You can prepare list of subdirectories (and files) at configuration stage, and then copy every element of that list using xcopy. This approach uses fact, that everything outside of build directory is not changed. Here iteration is done on configuration stage (by CMake). I am not sure, whether "for" loop works under COMMAND of add_custom_command. If it works, you can use it for iterate over entries in the shell.
CMakeLists.txt:
# List of elements in source directory.
file(GLOB entries RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
# List of commands for pass to `add_custom_command` as is.
# `COMMAND` keyword is included into list.
set(copy_commands)
foreach(entry ${entries})
list(APPEND copy_commands COMMAND xcopy /s /i
${CMAKE_CURRENT_SOURCE_DIR}/${entry} ${CMAKE_CURRENT_SOURCE_DIR}/build/${entry}
endforeach()
add_custom_command(... ${copy_commands})

Related

Visual Studio Solution Style using CMakelists [duplicate]

I have a CMake project that looks like this:
project/
CMakeLists.txt
subprojectA/
CMakeLists.txt
include/
headerA.hpp
src/
libraryA.cpp
subprojectB/
CMakeLists.txt
src/
mainB.cpp
The "library" subproject, A, is compiled as a static library, becoming libsubprojectA.a. The "main" project, B, is compiled as a binary and depends on the library. mainB.cpp includes a reference to headerA.hpp.
Here is subprojectA/CMakeLists.txt:
project(SubProjectA)
include_directories(include)
add_library(subprojectA STATIC src/libraryA.cpp)
set(${PROJECT_NAME}_INCLUDE_DIRS
${PROJECT_SOURCE_DIR}/include
CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
And here is subprojectB/CMakeLists.txt:
project(SubProjectB)
include_directories(${SubProjectA_INCLUDE_DIRS})
add_executable(mainBinary src/mainB.cpp)
target_link_libraries(mainBinary subprojectA)
The main Project CMakeLists.txt looks like:
project(Project)
add_subdirectory(subprojectB)
add_subdirectory(subprojectA)
Note that subprojectB, the main project, is listed before subprojectA.
Here's the problem. When I first run "cmake" on this project, ${SubProjectA_INCLUDE_DIRS} is not set within SubProjectB.
What I think is happening is that the CMakeLists for SubProjectB loads first, when ${SubProjectA_INCLUDE_DIRS} has not yet been set. It sets its own include path to an empty string as a result. However, even though libsubprojectA.a gets built successfully before mainBinary, the include path was already set empty beforehand. As a result, I get this error when trying to make mainBinary:
subprojectB/src/mainB.cpp:1:23: fatal error: headerA.hpp: No such file or directory
#include "headerA.hpp"
^
It's a workaround to put subprojectA before subprojectB in the main Project CMakeLists in the declarative world of CMake. What I really want is to know the proper way to indicate to CMake that the include_directories(${SubProjectA_INCLUDE_DIRS}) line depends on the definitions that exist inside SubProjectA's CMakeLists. Is there a better way to do this?
If you want to express that include directory subprojectA/include is an interface of the library subprojectA, attach this property to the target with target_include_directories command:
subprojectA/CMakeLists.txt:
project(SubProjectA)
add_library(subprojectA STATIC src/libraryA.cpp)
# PUBLIC adds both:
# 1) include directories for compile library and
# 2) include directories for library's interface
target_include_directories(subprojectA PUBLIC include)
So any executable(or other library) which linked with subprojectA will have this include directory automatically:
subprojectB/CMakeLists.txt:
project(SubProjectB)
add_executable(mainBinary src/mainB.cpp)
target_link_libraries(mainBinary subprojectA)
Of course, for use last command properly you need to process directory with library before one with executable:
CMakeLists.txt:
project(Project)
add_subdirectory(subprojectA)
add_subdirectory(subprojectB)

Creating a CMakeLists.txt with header and mains

I have divided my program in 3 folders: build, include, and src.
Build is where I want all the files created from the Makefile to go, include contains a "file.h", and src contains a "file.c" and "main.c".
I have written this in the CMakeLists.txt file:
cmake_minimum_required (VERSION 3.5.1)
project(Listas_interlazadas)
include_directories(${include})
add_executable(ejec
src/main.c
src/listas.c
include/listas.h
)
Nonetheless, I believe I should somehow include the src folder. Also, how do I send all files to the build folder? From the terminal, right?
Thanks.
Your code need some minor reworks.
The command include_directories must point to an valid path
Add header files only in case they are not included in any of your source files
Assume the following structure of your project:
project
+--source
| +--CMakeLists.txt
| +--src
| | +--main.c
| | +--listas.c
| +--include
| +--listas.h
+--build
Reworked CMakeLists.txt
cmake_minimum_required (VERSION 3.5.1)
project(Listas_interlazadas)
include_directories(include)
add_executable(ejec
src/main.c
src/listas.c
)
Back to your questions:
Add the sources: You already inserted the required source files. See add_executable.
Copy sources to build folder: This is not necessary.
To build your project, you have to run cmake and make (or nmake on windows).
Steps:
Open a command shell
Move to the build folder
Run: cmake ../source
Run: make
Some important parts of a CMakeLists.txt

Use a variable of another project in Build Events

I have a solution containing multiple projects. I can use project variables within Build Events, for example $(TargetDir) to access paths and files of the current project.
Solution 'MyApp'
MyApp
MyApp.Core
MyApp.Setup
I want to add a Pre-Build-Event in MyApp.Setup. The $(TargetDir) would return D:\MyApp\MyApp.Setup\bin\Debug, but I want to gather all files from MyApp-Output Directory and put them into the setup directory.
So is it possible to access variables from other projects within build events?
Something like that:
copy "$(MyApp.TargetDir)\*.*" "$(ProjectDir)\externals"
I propose you build all projects of solution into one folder, and inside that folder create specific project subfolders. For now your projects have TargetDir variable with values:
MyApp - D:\MyApp\MyApp\bin\Debug
MyApp.Core - D:\MyApp\MyApp.Core\bin\Debug
MyApp.Setup - D:\MyApp\MyApp.Setup\bin\Debug
But you can make common target directory, so TargetDir value:
MyApp - D:\MyApp\Debug\MyApp\bin
MyApp.Core - D:\MyApp\Debug\MyApp.Core\bin
MyApp.Setup - D:\MyApp\Debug\MyApp.Setup\bin
And in Pre-Build-Event you can refer to it:
copy "$(TargetDir)\..\MyApp\*.*" "$(ProjectDir)\externals"

Windows Compact Embedded - Include external native files

I have created a Sub project which just prints "Hello World". My goal is to create a C file inside the same subproject but within a folder named "src", also I want to create a H file within a folder named "include".
The H file contains only one function declaration "void printContent();" and the C file contains its definition which prints "Hello Buddy".
I added the C file inside the Source Files section of Sub project and added the H file inside the Header File Section, but when I compile the subproject and try to deploy it on to an emulator, I got an error.
BUILD: [01:0000000047:ERRORE] NMAKE : U1073: don't know how to make 'obj\ARMV4I\debug\content.obj'
I tried to configure the subproject by providing the below lines in the sources file of every Sub project.
INCLUDES= include/
But nothing changed and the problem still persists.
In wince subproject, sub folders are treated differently in the source file layout.
Rule No.1 You can't have both source and dirs files in the same folder.
So you either use one folder, or use several sub folders, then the root folder is clean and have one dirs file and several folders, no source file.
Rule No. 2 Each sub folder should have both source and makefile
You can copy and then edit the source file, the makefile will always be the same.
Ok, if you are going to use subfolder just to make the folder structure cleaner, my suggestion is that you create 2 subprojects, one is the main subproject; the other includes all your src files and its type is set to be static library. Then you can link to the static .lib file just as you are including them as in a subfolder. Of cource you need to set the additional include folder and input library.

SCons: directory dependency in a parallel build

I'm having trouble with a directory dependency in a parallel build in SCons.
Consider two projects with a single SConstruct in the following (simplified) hierarchy:
- SConstruct
- project1
- src
- project2
- src
- build
- project1
- project2
- dist
- project1
- project2
Each of project1 and project2 are supposed to be built under the relevant build directory (using variant dir) and several targets needs to be installed under the relevant dist directory.
Project 2 depends on Project 1's dist. I've states this dependency explicitly using the Depends() statement like so:
Depends('project2', 'dist/project1')
When I use a non-parallel build, there's no problem. Project 1 is fully built, targets are installed in the dist directory, and only then project 2 is built. However, when I use multiple jobs (4), project 2 is being built simultaneously to the Install() builder being run for the files needed to be installed in project 1's dist directory.
So, my questions are:
Does the Depends(project2, dist/project1) statement refers to the creation of the dist/project1 directory or to the completion of building all the directory's children?
How should I solve this issue?
Thank you very much,
BugoK.
Instead of specifying the actual directories as strings in the Depends() function, try specifying the actual targets as returned by the SCons project1 and project2 builders. Every SCons builder (or at least most of them) returns the affected target as an object, and its better to use this object instead of the file/directoy name since if you dont use the exact same file/directory path, it wont be considered as the same target.
Here is an example, fill in content accordingly:
project2Target = Install()
# Im not sure how you're building project1, so replace the builder
project1Target = Proj1DistBuiler()
Depends(project2Target, project1Target)

Resources