CMake How to access headers and source files in a different folder - cmake

I have a code repository like image below. I'm trying to add a new standalone executable. The main.cpp and CMakeLists.txt files are located in folder4 and main.cpp requires code from folder3.
At the moment I'm using:
cmake_minimum_required(VERSION 3.10)
# set the project name
project(Standalone)
# add the executable
add_executable(StandaloneExe main.cpp)
Should I now use file( GLOB SRCS *.cpp *.h ) to retrieve the headers and source files from folder3?
I just want the simplest way of generating this executable.

Should I now use file( GLOB SRCS *.cpp *.h ) to retrieve the headers and source files from folder3?
No, you should never use GLOB to get sources. See my answer here for more detail: https://stackoverflow.com/a/65191951/2137996
I just want the simplest way of generating this executable.
Put your CMakeLists.txt in the root instead. Then just write:
cmake_minimum_required(VERSION 3.10)
# set the project name
project(Standalone)
# add the executable
add_executable(
StandaloneExe
folder2/folder4/main.cpp
folder1/folder3/a.cpp
folder1/folder3/b.cpp
)
# Might need this, maybe not, depending on your includes
target_include_directories(
StandaloneExe
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/folder1/folder3"
)
If you absolutely cannot move your lists file, then you can use absolute paths:
add_executable(
StandaloneExe
${CMAKE_CURRENT_LIST_DIR}/../../folder2/folder4/main.cpp
${CMAKE_CURRENT_LIST_DIR}/../../folder1/folder3/a.cpp
${CMAKE_CURRENT_LIST_DIR}/../../folder1/folder3/b.cpp
)

Related

Why CMake C/C++ treats two binary library differently? (detail inside)

Here's my CMake script:
cmake_minimum_required(VERSION 2.8)
project(cimutils)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
# not recommended to search for all *.c (This sets all source in variable SOURCES)
#file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "*.c")
# explicitly define each .c file is preferred. (This sets all source in variable SOURCES)
set(SOURCES
"src/process_picture/saveraw.c"
"src/process_picture/savebmp.c"
"src/process_picture/savejpeg.c"
"src/lcd/framebuffer.c"
"src/main.c"
"src/cim/video.c"
"src/cim/process.c"
"src/cim/convert.c"
"src/cim/cim_fmt.c"
)
# set include path in variable INC
set (INC
"src/include"
"src/jpeg_hw_encoder"
)
# Set include path
include_directories (AFTER ${INC})
# Set all source files
add_executable(${PROJECT_NAME} ${SOURCES})
# Sets default (system) library path
set (CMAKE_SYSROOT "/usr/local/mips-linux-gnu-gcc-toolchains/mips-gcc-glibc/mips-linux-gnu/libc")
find_library (jpeg
NAMES jpeg
PATHS "${CMAKE_SOURCE_DIR}/lib"
)
find_library (jpeg-hw
NAMES jpeg-hw
PATHS "${CMAKE_SOURCE_DIR}/lib"
)
target_link_libraries(${PROJECT_NAME} c gcc_s ${jpeg} ${jpeg-hw})
The build is OK. However, it treated jpeg-hw and jpeg differently, since I saw the link command (detail truncated, to show only the relevant parts) to be:
gcc ..... ${PROJECT_HOME}/lib/libjpeg.so -ljpeg-hw
Apparently, these two binary libraries were placed in the same directory, and they uses the same syntax in the script file. But why CMake choose full path for one, and choose to use -l for the other? Just very curious....

how to use CMake file (GLOB SRCS *. ) with a build directory

this is my current CMakeLists.txt file
cmake_minimum_required(VERSION 3.3)
set(CMAKE_C_FLAGS " -Wall -g ")
project( bmi )
file( GLOB SRCS *.cpp *.h )
add_executable( bmi ${SRCS})
This builds from my source directory, but I have to clean up all the extra files after. My question is how do I build this from a build directory if all my source files are in the same source directory?
thanks
If you really need to use file(GLOB …), this CMakeLists.txt should work :
cmake_minimum_required(VERSION 3.3)
project(bmi)
add_definitions("-Wall" "-g")
include_directories(${PROJECT_SOURCE_DIR})
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
add_executable(bmi ${SRC_FILES})
In this case you have to launch cmake from your build directory every time you add or delete a source file :
cmake <your_source_dir> -G <your_build_generator>
As Phil reminds, CMake documentation doesn't recommend this use of GLOB. But there are some exceptions. You'll get more information on this post.
If you don't meet those exceptions, you'd rather list your source files than use GLOB :
set(SRC_FILES ${PROJECT_SOURCE_DIR}/main.cpp
${PROJECT_SOURCE_DIR}/bmi.cpp
… )
NB : if you have #include of your .h files in .cpp files, I don't see any reason to put them in add_executable, you just need to specify include directory with include_directories.
Cmake used to only update the list of source files if CMakeLists.txt was changed since the last cmake run or if cmake was used to configure the project again.
In cmake 3.11.0 recursive search and automatic re-configuration on adding or deleting source files was added. Since then you can use the following snippet:
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.11.0")
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp *.h)
else()
file(GLOB SOURCE_FILES *.cpp *.h */*.h */*.cpp)
endif()
The file() command after the else() provides at least a bit of backwards compatibility: It still searches for source files in the current folder and its direct subfolders. But it doesn't automatically recognize if there are new files or old files have been deleted.
Note that VERSION_GREATER_EQUAL is only available in cmake >= 3.7

Simple CMakeLists.txt that reflects typical directory structure (/src, /inc, /bin subdirectories)

I am struggling to make a CMakeList.txt file to reflect a simple, typical makefile. The original is here http://pastebin.com/S9Czr1pt .
I tried many things (like SET(SOURCE ... and SET(HEADERS... ) to add /src, /lib and /third-party//include ), but I have no luck.
Can anyone either help me out or point to a tutorial that does this thing?
This is just an out of the blue skeleton - please see the CMake documentation for details of each function:
cmake_minimum_required(VERSION 2.6)
# Project name, can be used as target name too
project(Example)
# Search all .cpp files within src - recursive!
# You can add all source files by hand here too
file(GLOB_RECURSE SRCS "src/*.cpp")
# Add include path (you can also add it's sub directories
include_directories("include")
# Search for packages -- PLEASE NOTE: many libraries provide alternative's to this
# which often provide more functionality
find_package(PkgConfig REQUIRED)
# TODO: add proper pkg modul search info's and change the variable's name
pkg_search_module(PACKAGE_NO1 ...)
# Show some messages (optional)
if( (PACKAGE_NO1 )
include_directories(${(PACKAGE_NO1_INCLUDE_DIRS})
message(STATUS "Using OpenSSL ${(PACKAGE_NO1_VERSION}")
else()
# do error handling
endif()
# Add compiler flags
add_definitions(-std=c++11 -Wall) # -g O3 etc are added according to Release / Debug compilation
# Build a executable target (1st param: Target name; 2nd: source files)
add_executable(${PROJECT_NAME} ${SRCS})

Add sources from other paths don't have CMakeLists.txt, and move output files to other path in CMake

My source tree:
/project
/project/src/<my sources>
/project/build/vs2008
/project/build/ubuntu
I want to put my CMakeLists.txt in vs2008 and ubuntu. I can accept put one CMakeLists.txt to each folder and put another global CMakeLists.txt on /project/build, but I just don't want any CMakeLists.txt in /project/src(So I can't use add_subdirectory command). I need my solution files of visual studio in /project/build/vs2008 and Makefile in /project/build/ubuntu. What commands I should know about?
I think there's nothing special you would need to know -- you just need to specify paths to your source files relative to where your CMakeLists.txt is located, and your targets should build the same as if you had placed CMakeLists.txt in your src folder. For example, project/build/ubuntu/CMakeLists.txt could look like this:
set( SrcDir ../../src )
add_executable( MyApp
${SrcDir}/file1.cpp
${SrcDir}/file2.cpp
# and so on
)

How do I make build rules in cmake to preprocess lazy C++ .lzz files that generate .h and .cpp files?

What I'd like to do is write just Lazy C++ .lzz files and then have lzz run before a build to generate .cpp and .h files that will be built into the final application, sort of like how moc works with Qt.
Is there any way to do this?
Here is an example of how to do this... First you need to find the lzz program, for that use the find_program command:
find_program(LZZ_COMMAND lzz)
This sets LZZ_COMMAND to the path of the compiler. Then use a CMake custom command to compile the LZZ file to their C++ header/implementation files:
add_custom_command(
OUTPUT ${output}
COMMAND ${LZZ_COMMAND} -o ${CMAKE_CURRENT_BINARY_DIR} ${filename})
That generates the files in the current build directory, in case you do out-of-source builds. You will also need to specify that the outputs are generated files:
set_source_files_properties(${output} PROPERTIES GENERATED TRUE)
Put that all together and you get a CMakeLists.txt file something like this:
cmake_minimum_required(VERSION 2.8)
project(lazy_test)
find_program(LZZ_COMMAND lzz)
function(lazy_compile filename)
get_filename_component(base ${filename} NAME_WE)
set(base_abs ${CMAKE_CURRENT_BINARY_DIR}/${base})
set(output ${base_abs}.cpp ${base_abs}.h)
add_custom_command(
OUTPUT ${output}
COMMAND ${LZZ_COMMAND} -o ${CMAKE_CURRENT_BINARY_DIR} ${filename})
set_source_files_properties(${output} PROPERTIES GENERATED TRUE)
endfunction()
lazy_compile(${CMAKE_CURRENT_SOURCE_DIR}/example.lzz)
add_executable(test example.cpp example.h)
You would probably also want to add include path and other options to lzz eventually. If you placed all the Lazy C++ stuff into a module file and included that from the CMakeLists.txt it would be a bit cleaner. But this is the basic idea.
I just wanted to share my CMakeLists.txt, which builds upon richq's script. The *.cpp and *.hpp files now properly depend on the *.lzz files. The *.lzz files are added to the project (which answers absense's question above) but kept separate from the generated files using the source_group command.
The only remaining dealbreaker for me is the inability to compile the current file for *.lzz files.
cmake_minimum_required(VERSION 2.8)
PROJECT(LzzTest)
find_program(LZZ_COMMAND lzz.exe)
# Syntax:
# add_lzz_file(<output> <lzz file>)
# Adds a build rule for the specified lzz file. The absolute paths of the generated
# files are added to the <output> list. The files are generated in the binary dir.
#
# TODO: Support for generating template files etc.
function(add_lzz_file output filename)
# Only process *.lzz files
get_filename_component(ext ${filename} EXT)
if(NOT ext STREQUAL ".lzz")
return()
endif()
set(header_extension "hpp")
get_filename_component(base ${filename} NAME_WE)
set(base_abs ${CMAKE_CURRENT_BINARY_DIR}/${base})
set(outfiles ${base_abs}.cpp ${base_abs}.${header_extension})
set(${output} ${${output}} ${outfiles} PARENT_SCOPE)
#message("outfiles=${outfiles}, DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${filename}")
add_custom_command(
OUTPUT ${outfiles}
COMMAND ${LZZ_COMMAND}
-o ${CMAKE_CURRENT_BINARY_DIR} # output dir
-hx ${header_extension}
-sl -hl -il -tl -nl -x # insert #line commands w/ absolute paths
-sd -hd -id -td -nd # don't output files that didn't change
${CMAKE_CURRENT_SOURCE_DIR}/${filename}
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${filename}"
)
set_source_files_properties(${outfiles} PROPERTIES GENERATED TRUE)
endfunction()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(SOURCES
A.lzz
B.lzz
main.cpp
)
foreach(file ${SOURCES})
add_lzz_file(GENERATED_SOURCES ${file})
endforeach()
source_group("" FILES ${SOURCES})
source_group(generated FILES ${GENERATED_SOURCES})
add_executable(LzzTest ${SOURCES} ${GENERATED_SOURCES})
For make:
sourcecode.h sourcecode.cpp: sourcecode.lzz
<TAB>lazy-cpp sourcecode.lzz
fill in sourcecode.h, sourcecode.cpp, and lazy-cpp with the correct values. I don't know them.