How to group header files in header subfolders under the general header files folder using Cmake - visual-c++

Hi I am building Cmake based build system.
I would like to group header files in folders (VC++ can do it) under the general folder Header Files.
Similar, I would like to group the corresponding .cpp files in folders under the Source Files directory.
Unfortunately I could not find any instructions of how to do it.
Please help.
Dimitre

You should give a look at CMake source_group command.

You can use source_group. Here's a concrete example.
Suppose you have a directory structure like:
|-include
| some.h
|-sub
| someother.h
|-src
| some.cpp
|-sub
|-someother.cpp
Collect the files (some people - including the documentation - discourages use of GLOB, but I leave that to you, you can list of them one by if you want to, though I find GLOB is just fine many times):
file(GLOB HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
file(GLOB HEADER_FILES_SUB "${CMAKE_CURRENT_SOURCE_DIR}/include/sub/*.h")
file(GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
file(GLOB SOURCE_FILES_SUB "${CMAKE_CURRENT_SOURCE_DIR}/src/sub/*.h")
# Setup your library or executable:
add_library(MY_LIB ${HEADER_FILES} ${HEADER_FILES_SUB}
${SOURCE_FILES} ${SOURCE_FILES_SUB})
# Here's the important part ("Header Files" and "Source Files" are literals.)
source_group("Header Files\\sub" ${HEADER_FILES_SUB})
source_group("Source Files\\sub" ${SOURCE_FILES_SUB})

Related

How to exclude files without an extension in Sublime Text 3?

I know there is an easy way to do it for known extensions, adding it in excluded patterns in preferences like "*.jpg", but how can I do it for the binary files without any extension at all?
In example, my c compiled files are named with just "name", not "name.o" etc, so is there any trick to exclude them?
To exclude a file with no extension then you must manually add the exact filename for each file that you want excluded.
Using your example, to exclude a file which is called name then add "name" to your file_exclude_patterns list like this:
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "name"],
Since you mention C compiled files then to avoid having to do this regularly with all your compiled executable files you can do one of several things or some combination or variation of them.
1) Consistently use the same executable file name, for example run, regardless of what you are compiling.
gcc example.c -o run
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "run"],
2) Choose a consistent prefix for the executable file names, for example run_.
gcc example.c -o run_example
gcc program.c -o run_program
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "run_*"],
3) Choose a file extension for your executables and use that consistently.
gcc example.c -o example.out
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.exe", ..., "*.out"],
Sorry to update an old question. As of today, we could instead specify "file_include_patterns": ["*.*"] in a project preference to exclude files without an extension from the sidebar.
The "file_include_patterns" consists of an array of glob strings, referred to by ST as file patterns. However, the file pattern of ST only supports two matching operators, * and ?. According to the document, File patterns specified under "file_include_patterns" are
Patterns of files to include from the folder. Anything not matching these patterns will be excluded. This is checked before "file_exclude_patterns".
One could further set the "index_include_patterns": ["*.*"] to prevent ST from indexing symbols from files without an extension. Differences between "file_include_patterns" and "index_exclude_patterns" can be found in #OdatNurd's answer.
An example project configuration file my-project.sublime-project that prevents ST from showing files without an extension in the side bar or indexing symbols from them may look like
{
"folders":
[
{
"file_include_patterns": ["*.*"],
"index_include_patterns": ["*.*"],
"path": "/path/to/your/my-project-folder"
}
]
}
where "/path/to/your/my-project-folder" needs to be set accordingly.
This setting prevents ST from showing or index files without an extension under "/path/to/your/my-project-folder" or its sub-folders.

How to add_library with pattern for sources?

I want to use regular expression to add all files to add_library, but it does not work.
I tried this :
add_library(8021qbg SHARED
8021QBG/"*.h"
8021QBG/"*.cpp"
)
And get this:
CMake Error at CMakeLists.txt:128 (add_library):
Cannot find source file:
8021QBG/"*.h"
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
I tried this:
file(GLOB 8021x
8021x/"*.h"
8021x/"*.cpp"
)
add_library(8021x SHARED
${8021x}
)
And at compiling make command does not see sources to compile.
I want to build shared library using something not to write down every source file (regular expression, I suppose).
How to do it?
You need to ask cmake to list all matching files into a variable:
file(GLOB SOURCE_FILES
8021QBG/*.h
8021QBG/*.cpp
)
and then use this variable:
add_library(8021qbg SHARED
${SOURCE_FILES}
)
More on file(GLOB) command.
Generate a list of files that match the and store it into the . Globbing expressions are similar to regular expressions, but much simpler.
With the following addition cmake is able to determine the name of the lib being added thus making the script context agnostic.
# libname = current directory name
get_filename_component(libname "${CMAKE_CURRENT_SOURCE_DIR}" NAME)
# .c and .h files
file(GLOB thislibsrc ${CMAKE_CURRENT_SOURCE_DIR}/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
# include it only once
include_guard(GLOBAL)
# and use it
add_library(${libname} STATIC ${thislibsrc} )
...
I have such little components saved in some central directory so I can call them later like:
include(../addlibscr.cmake)

CMake recursively add all source files inside all subdirectories of a directory to the executable?

I have a pretty big file structure of a project which I need to convert into a multiplatform cmake project. Now it seams that cmake requires ever single cpp file be added individually to the executable. But is there a script that automates this? That snoopes through the file structure and just adds every source file automatically? Since the project will probably get a lot more source files and I probably wont be able to manually add every single one.
You could use execute_process() with a cmake -P script that uses globbing to recursively scan for source files which writes to an included file in your CMakeLists.txt i.e. something like:
"CMakeLists.txt":
execute_process(COMMAND ${CMAKE_COMMAND}
-D "RDIR=${CMAKE_CURRENT_SOURCE_DIR}"
-P "scansources.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
include("sources.cmake")
add_executable(myexe ${sources})
"scansources.cmake" (generates "sources.cmake"):
file(GLOB_RECURSE sourcelist
*.c
*.cc
*.cpp
*.cxx)
string(REGEX REPLACE "${RDIR}/" "" relative_sources "${sourcelist}")
string(REPLACE ";" "\n" sources_string "${relative_sources}")
set(sources_string "set(sources\n${sources_string})")
file(WRITE sources.cmake "${sources_string}")
The reason why this works is because execute_process() occurs at configure time.
You could, of course, generate sources.cmake via some other tool or IDE then you wouldn't need scansources.cmake or execute_process().

zip files using CMake?

tl;dr version:
Is it possible with CMake (>= 2.8) to generate zip files from some files and put the packed zip file in a specific location?
longer version:
I have a CMakeLists.txt that builds my project into a .exe file, and this exe file will read data from a zip file. The content to be packed in the zip file is in my git repository so that it can be edited, too. But, the program needs this data in a zip file. So it would be good if the CMake script could take the data, put it in a zip file, and place it next to the exe. I already heard of CPack, but I did not find any easy examples and am not sure if this is even the right tool for my task.
Is this possible? If yes, how?
Since version 3.2 CMake has the functionality to generate a zip file built-in. The CMake command-line mode sub-command tar supports both the creation of zip and 7zip archives.
For example, if the current CMake source directory contains the file testfile.txt and the directory testdir, you can use the following CMake commands to create a zip file containing both items:
add_custom_target(create_zip COMMAND
${CMAKE_COMMAND} -E tar "cfv" "archive.zip" --format=zip
"${CMAKE_CURRENT_SOURCE_DIR}/testfile.txt"
"${CMAKE_CURRENT_SOURCE_DIR}/testdir")
As a work-around for earlier CMake versions, you can use the jar command that is part of a standard Java JRE installation.
find_package(Java)
execute_process(
COMMAND
"${Java_JAR_EXECUTABLE}" "cfM" "archive.zip"
"-C" "${CMAKE_CURRENT_SOURCE_DIR}" "testfile.txt"
"-C" "${CMAKE_CURRENT_SOURCE_DIR}" "testdir"
RESULT_VARIABLE _result
)
The zip file will be generated in the current CMake binary dir (CMAKE_CURRENT_BINARY_DIR).
It's never late to show real answer:
function(create_zip output_file input_files working_dir)
add_custom_command(
COMMAND ${CMAKE_COMMAND} -E tar "cf" "${output_file}" --format=zip -- ${input_files}
WORKING_DIRECTORY "${working_dir}"
OUTPUT "${output_file}"
DEPENDS ${input_files}
COMMENT "Zipping to ${output_file}."
)
endfunction()
Use like
file(GLOB ZIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/zip/*")
create_zip("${CMAKE_CURRENT_BINARY_DIR}/native_data.zip" "${ZIP_FILES}" "${CMAKE_CURRENT_SOURCE_DIR}/zip")
This will pack all files from zip/ subdirectory into native_data.zip (in build directory). Then either include your archive (path will differ in different CMakeLists.txt!) as source file or add it as target:
add_custom_target("project-data" ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/native_data.zip")
Install will not differ a lot from usual:
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/native_data.zip" DESTINATION ${DATADIR} RENAME "data000.zip") # Install our zip (as data000.zip)
I assume you already have a zip-tool installed (WinZip or 7z, etc.). You could write a find_zip-tool script which will search for WinZip, or 7Z, etc...
Snippet for WinZip:
FIND_PROGRAM(ZIP_EXECUTABLE wzzip PATHS "$ENV{ProgramFiles}/WinZip")
IF(ZIP_EXECUTABLE)
SET(ZIP_COMMAND "\"${ZIP_EXECUTABLE}\" -P \"<ARCHIVE>\" #<FILELIST>")
ENDIF(ZIP_EXECUTABLE)
Snippet for 7-zip:
FIND_PROGRAM(ZIP_EXECUTABLE 7z PATHS "$ENV{ProgramFiles}/7-Zip")
IF(ZIP_EXECUTABLE)
SET(ZIP_COMMAND "\"${ZIP_EXECUTABLE}\" a -tzip \"<ARCHIVE>\" #<FILELIST>")
ENDIF(ZIP_EXECUTABLE)
Take a look at the file
<cmake-install-dir>\share\cmake-2.8\Modules\CPackZIP.cmake
it shows how CPack searches for a Zip_Executable and prepares some "useful" default flags.
After that, I would suggest to execute_process, similar to sakra's answer
As of version 3.18, CMake now directly supports creating zip or archive files using the file() command with ARCHIVE_CREATE:
file(ARCHIVE_CREATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/MyData.zip
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/data
FORMAT zip
)
Be sure to specify a full path for the OUTPUT zipped filename, or the file may not be generated. Also, the PATHS option accepts files or directories to be placed in the zip file, but it does not accept wildcards at the time of writing.
This command supports several archive formats and compression flavors. So, you can use the same command to create tarballs as well:
file(ARCHIVE_CREATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/MyData.tar.gz
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/data
FORMAT gnutar
COMPRESSION GZip
)
Since this is the top search result for creating zip files with CMake, here is a CPack solution for completeness. The basic idea is that you make calls to install() and then tell it what to name the resulting zip file. It will be placed in the build directory, though there may be a way to change that. Then you can create the zip file with make package or cpack.
# Version 1: Subtractive
# Include everything in the project source directory.
# Put it at the top level of the zip via `DESTINATION .`
# Subtract things we don't want.
# The trailing slash after "${PROJECT_SOURCE_DIR}/" prevents
# an extra layer of directories.
install(DIRECTORY "${PROJECT_SOURCE_DIR}/"
DESTINATION .
PATTERN ".git*" EXCLUDE
PATTERN ".DS_Store" EXCLUDE
PATTERN "examples" EXCLUDE
PATTERN "docs" EXCLUDE
PATTERN "README.md" EXCLUDE
)
# Version 2: Additive
# Include only the list of things we specify.
# Put it at the top level of the zip via `DESTINATION .`
# install(FILES
# ${SRCS}
# "Notes.txt"
# DESTINATION .
# )
# Tell CPack to create a zip file.
set(CPACK_GENERATOR "ZIP")
# Tell CPack what to name the zip file. It will append `.zip`.
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}")
# Tell CPack not to put everything inside an enclosing directory.
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
# Apparently this should be always on but isn't for backwards compatibility.
set(CPACK_VERBATIM_VARIABLES YES)
include(CPack)
Essentially what I did was create custom target
add_custom_target(STAGE_FILES)
With this target I copy the files and directories to the CMAKE_CURRENT_BINARY_DIR
add_custom_command(
TARGET STAGE_FILES
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/assets/video ${CMAKE_CURRENT_BINARY_DIR}/video
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/assets/data ${CMAKE_CURRENT_BINARY_DIR}/data
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/assets/strings_en.csv ${CMAKE_CURRENT_BINARY_DIR}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/assets/strings_rules_en.csv ${CMAKE_CURRENT_BINARY_DIR}/
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "data.zip" --format=zip --files-from=${CMAKE_SOURCE_DIR}/assets/to_zip.txt
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/data
COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/data.zip ${CMAKE_CURRENT_BINARY_DIR}/data
)
The important line
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "data.zip" --format=zip --files-from=${CMAKE_SOURCE_DIR}/assets/to_zip.txt
inside my
to_zip.txt
I specify all the files I want to include in my zip
data/
video/
...
I can now execute the command
make STAGE_FILES
which will copy and zip everything i need

Including header files in cygwin

As you know the getch() and getche() functions don't work with the cygwin, a linux oriented one.
But can I include the conio.h header file of borland c and call the functions getch in my makefiles?
Will it work and can anyone tell me how to include the header files from different directories in cywgin.
I have a header file strcal.h in directory c:/makk/string/.
How do I include that header file in my makefile?
gcc -I/string small.c
It is not working and my current directory is makk.
In stdio.h, there is a getchar() function which is what you need. You can't just bring across the Borland header file since that just declares the function, it doesn't define it. Standard C has no need for getch().
To include header files in different areas, you use the -I directives of gcc to set up search paths.
So, if you have a /xyz/myheader.h file, you can do something like:
gcc -I /xyz myprogram.c
To get at c:/makk/string/strcal.h, you may have to use gcc -I /cygdrive/c/makk/string or, if you know you're actually in that makk directory, you can use -I string (note the lack of leading / since you want a relative path, not an absolute one).

Resources