I want to collect all the source or header files from a specified folder, also matching a curtain naming convention. I don't want to use GLOBbing, and also couldn't find any examples of an approach using only cmake.
One answer from this question suggests to use ls *.cpp
into CMakeLists.txt
. So I though of getting a list of sources via invoking a batch script in CMakeLists.
But something is wrong. Though it seems that the output is totally correct, CMake can not find those files. The path is (visually) correct: if I manually type it into add_executable
, generating will succeed.
While I still want to know how to achieve the initial intent, I am extremely confused about the reason why totally identical strings compare to false:
CMake log:
-- Manually-typed: C:/Repos/cmake-scanner/src/main.cpp
-- Recieved-batch: C:/Repos/cmake-scanner/src/main.cpp
-- Path strings not identical
CollectSources.bat
@echo off
set arg1=%1
set arg2=%2
powershell -Command "$path = '%1'.Replace('\','/'); $headers = New-Object Collections.Generic.List[string]; ls -Name $path/*.%2 | foreach-object{ $headers.Add($path + '/' + $_)}; $headers"
CMakeLists.txt
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(Auto-scanner)
set(HEADERS)
set(SOURCES)
if(WIN32)
execute_process(
COMMAND CMD /c ${CMAKE_CURRENT_SOURCE_DIR}/CollectSources.bat ${CMAKE_CURRENT_SOURCE_DIR}/include h
OUTPUT_VARIABLE res
)
message(STATUS "Found headers: ${res}")
execute_process(
COMMAND CMD /c ${CMAKE_CURRENT_SOURCE_DIR}/CollectSources.bat ${CMAKE_CURRENT_SOURCE_DIR}/src cpp
OUTPUT_VARIABLE res2
)
message(STATUS "Found sources: ${res2}")
set(${HEADERS} ${res})
endif(WIN32)
message(STATUS "Collected headers: ${HEADERS}")
message(STATUS "Manually-typed: C:/Repos/cmake-scanner/src/main.cpp")
message(STATUS "Recieved-batch: ${res2}")
if(NOT "C:/Repos/cmake-scanner/src/main.cpp" STREQUAL "${res2}")
message(STATUS "Path strings not identical")
else()
message(STATUS "Path strings are identical")
endif()
add_executable(${PROJECT_NAME}
${res}
${res2}
)
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
and project tree:
cmake-scanner
|-include
| |-IPublicA.h
| |-IPublicB.h
| |-IPublicC.h
| |-IPublicD.h
|-src
|-main.cpp
https://github.com/ElDesalmado/cmake-scanner.git
UPDATE
Strings' comparison by length yields different results, so I thought maybe there are some trailing characters in the output of execute_process
.
So I replaced all the newlines that actually might prevent cmake from finding source files.
string(REGEX REPLACE "\n$" "" ...)
So they compare equal, however still could not be located by cmake.
I had some luck with using OUTPUT_STRIP_TRAILING_WHITESPACE
in execute_command
and main.cpp
has been finally located and project generated. But when there are 2 or more sources this doesn't help.
I m going to try outputting sources' names in a single line and see what would occur...
I have solved the issue.
Cmake accepts lists of sources that must be formatted in a way, that sources' paths are separated with a semicolon. So the solution was to modifiy batch script to output a string line of semicolon-separated file names. Later I will update the repo and provide the batch code.