CMake FindFLEX produces NOTFOUND on windows - c++

I installed flex and bison with chocolatey
choco install winflexbison3
and created this CMakeLists.txt
find_package(BISON)
find_package(FLEX)
message("FLEX_FOUND: ${FLEX_FOUND}")
message("FLEX_EXECUTABLE: ${FLEX_EXECUTABLE}")
message("FLEX_INCLUDE_DIRS: ${FLEX_INCLUDE_DIRS}")
message("FLEX_LIBRARIES: ${FLEX_LIBRARIES}")
BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp)
FLEX_TARGET(MyScanner lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp)
ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(Foo
${BISON_MyParser_OUTPUTS}
${FLEX_MyScanner_OUTPUTS}
)
target_link_libraries(Foo ${FLEX_LIBRARIES})
I wrote a dummy parser (copied from https://aquamentus.com/flex_bison.html)
and tried to build the project
-- Found BISON: C:/ProgramData/chocolatey/bin/win_bison.exe (found version "3.7.4")
-- Found FLEX: C:/ProgramData/chocolatey/bin/win_flex.exe (found version "2.6.4")
FLEX_FOUND: TRUE
FLEX_EXECUTABLE: C:/ProgramData/chocolatey/bin/win_flex.exe
FLEX_INCLUDE_DIRS: FLEX_INCLUDE_DIR-NOTFOUND
FLEX_LIBRARIES: FL_LIBRARY-NOTFOUND
CMake Warning (dev) in CMakeLists.txt:
No cmake_minimum_required command is present. A line of code such as
cmake_minimum_required(VERSION 3.23)
should be added at the top of the file. The version specified may be lower
if you wish to support older CMake versions for this project. For more
information run "cmake --help-policy CMP0000".
This warning is for project developers. Use -Wno-dev to suppress it.
-- Configuring done
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
FL_LIBRARY (ADVANCED)
linked by target "Foo" in directory C:/Users/Aleksander/source/repos/C/insilico/blender/test
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
For some reason CMake can't find the library and include dir. What should I do? Where does FLEX expect the libraries to be?
This is what I did so far:
I see FlexLexer.h to be right there
C:\ProgramData\chocolatey\lib\winflexbison3\tools> ls
FlexLexer.h changelog.md custom_build_rules win_bison.exe
UNISTD_ERROR.readme chocolateyInstall.ps1 data win_flex.exe
I see that FindFLEX uses this source code to look for this file but somehow fails
https://github.com/Kitware/CMake/blob/241fc839d56ccd666fe41269e291b8d8190cf97b/Modules/FindFLEX.cmake#L117
find_library(FL_LIBRARY NAMES fl
DOC "Path to the fl library")
find_path(FLEX_INCLUDE_DIR FlexLexer.h
DOC "Path to the flex headers")
mark_as_advanced(FL_LIBRARY FLEX_INCLUDE_DIR)
set(FLEX_INCLUDE_DIRS ${FLEX_INCLUDE_DIR})
set(FLEX_LIBRARIES ${FL_LIBRARY})
I found this documentation for find_path
http://devdoc.net/linux/cmake-3.9.6/command/find_path.html
and there is a list of paths that are searched. I queried them with
message("CMAKE_INCLUDE_PATH: ${CMAKE_INCLUDE_PATH}")
message("CMAKE_FRAMEWORK_PATH: ${CMAKE_FRAMEWORK_PATH}")
message("CMAKE_SYSTEM_INCLUDE_PATH: ${CMAKE_SYSTEM_INCLUDE_PATH}")
message("CMAKE_SYSTEM_FRAMEWORK_PATH: ${CMAKE_SYSTEM_FRAMEWORK_PATH}")
message("CMAKE_LIBRARY_ARCHITECTURE: ${CMAKE_LIBRARY_ARCHITECTURE}")
message("CMAKE_FIND_ROOT_PATH: ${CMAKE_FIND_ROOT_PATH}")
message("CMAKE_SYSROOT: ${CMAKE_SYSROOT}")
and got
CMAKE_INCLUDE_PATH:
CMAKE_FRAMEWORK_PATH:
CMAKE_SYSTEM_INCLUDE_PATH:
CMAKE_SYSTEM_FRAMEWORK_PATH:
CMAKE_LIBRARY_ARCHITECTURE:
CMAKE_FIND_ROOT_PATH:
CMAKE_SYSROOT:
So it seems that find_path does absolutely nothing. Should I specify the paths myself? But is such case what is CMake even for?

It's astounding how many irritating problems are caused by a trivial library file which probably shouldn't exist anyway, and which is hardly ever needed.
The library in question was originally called libl (l for lex), and Posix requires that when you link executables which include a lex-generated scanner, you add -ll to the linker invocation. Flex, which to all intents and purposes is the current successor to the Lex tool, decided to change the name of the library to libfl, and that's generally what you'll find in a Flex installation. So the usual instructions you'll find these days (i.e., for the last several decades) say that you should use the command-line option -lfl.
Often, but not always, distributions add a symbolic link (or equivalent) for libl so that the Posix-specified -ll still works. Occasionally, the Flex distribution is modified so that the library is called libl, in which case -lfl won't work. And sometimes, the library isn't part of the distribution at all and needs to be acquired from a different package.
Posix wanted to cater for a Lex implementation which puts some functions into a library instead of generating the same code each time. But few (if any) lex implementations ever took advantage of that provision; in particular, Flex-generated scanners have no reliance on libfl for any internal function. There are only two functions defined in that library:
int main(void) { while (yylex()) {} }
int yywrap(void) { return 1; }
The first one is a default implementation of main which just calls yylex until it returns 0 (indicating EOF). That can be handy for quick-and-dirty scanner rule tests, but any real project will certainly have a main() definition.
The second provides a default yywrap implementation. However, Flex provides an even simpler way of indicating that the yywrap functionality isn't required:
%option noyywrap
If you don't require yywrap, you should just add the above to your .l file (in the prologue). If you do require yywrap, then you need to define it. In either case, you don't need the library.
So my recommendation is that rather wasting your time trying to figure out the deficiencies of the flex packaging you're using, just add the above %option to your Flex input file and eliminate the library from your build rules.

Related

How to fix "Could not find a package configuration file ..." error in CMake?

I have been working on a project which uses rplidar_sdk and in the beginning, I was facing this problem:
How can I link locally installed SDK's static library in my C++ project?
Basically, the SDK generates the library in its local directory, and in its Makefile, it does not have install rules. I mean I can run make but after that, if I run sudo make install then it gives make: *** No rule to make target 'install'. Stop. error.
So, with the help of this & this answer, I was able to build my local project. So far so good.
However, the main problem is that I have to hard-code the RPLidar SDK path in CMakeLists.txt of my repo. Now, whenever someone else in my team starts working on that repo (which is quite obvious) then he/she has to update the CMakeLists.txt first. This is not a good idea/practice!
To fix this, I updated the Makefile of RPLidar SDK as follow:
.
.
.
RPLIDAR_RELEASE_LIB := $(HOME_TREE)/output/Linux/Release/librplidar_sdk.a
install: $(RPLIDAR_RELEASE_LIB)
install -d $(DESTDIR)/usr/local/lib/rplidar/Release/
install -m 644 $(RPLIDAR_RELEASE_LIB) $(DESTDIR)/usr/local/lib/rplidar/Release/
RPLIDAR_DEBUG_LIB := $(HOME_TREE)/output/Linux/Debug/librplidar_sdk.a
install: $(RPLIDAR_DEBUG_LIB)
install -d $(DESTDIR)/usr/local/lib/rplidar/Debug/
install -m 644 $(RPLIDAR_DEBUG_LIB) $(DESTDIR)/usr/local/lib/rplidar/Debug/
RPLIDAR_HEADERS := $(HOME_TREE)/sdk/include
install: $(RPLIDAR_HEADERS)
install -d $(DESTDIR)/usr/local/include/rplidar/
cp -r $(RPLIDAR_HEADERS)/* $(DESTDIR)/usr/local/include/rplidar/
RPLIDAR_HEADERS_HAL := $(HOME_TREE)/sdk/src/hal
install: $(RPLIDAR_HEADERS_HAL)
install -d $(DESTDIR)/usr/local/include/rplidar/
cp -r $(RPLIDAR_HEADERS_HAL) $(DESTDIR)/usr/local/include/rplidar/
Due to this update, now, I can run sudo make install which basically copies the header files of RPLidar SDK from the local directory to /usr/local/rplidar/ directory. It also copies the lib file to /usr/local/lib/rplidar/<Debug> or <Release>/ directory.
Now, in my local project, I updated the CMakeLists.txt to as follow:
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(<project_name>)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
SET(CMAKE_CXX_FLAGS -pthread)
include_directories(include)
add_executable(${PROJECT_NAME} src/main.cpp src/another_src_file.cpp)
find_package(rplidar REQUIRED)
include_directories(${rplidar_INCLUDE_DIRS})
link_directories(${rplidar_LIBRARY_DIRS})
target_link_libraries(${PROJECT_NAME} ${rplidar_LIBRARY})
However, upon running cmake .. command, I'm getting this error:
.
.
.
CMake Error at CMakeLists.txt:12 (find_package):
By not providing "Findrplidar.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "rplidar", but
CMake did not find one.
Could not find a package configuration file provided by "rplidar" with any
of the following names:
rplidarConfig.cmake
rplidar-config.cmake
Add the installation prefix of "rplidar" to CMAKE_PREFIX_PATH or set
"rplidar_DIR" to a directory containing one of the above files. If
"rplidar" provides a separate development package or SDK, be sure it has
been installed.
-- Configuring incomplete, errors occurred!
As far as I know, RPLidar SDK does not have rplidarConfig.cmake or rplidar-config.cmake file.
How can I fix this error?
Rants from my soul:
It sucks when you have to use any library foo when the author fails to provide a foo-config.cmake for you to use easily by invoking find_package(foo). It's absolutely outrageous when a reasonably modern project still uses hand written Makefiles as its build system. I myself is stuck with a much worse constructed SDK than yours right now.
Short answer:
Since the author of the SDK fails to provide a config file to support your cmake usage, if you still insists on invoking find_package on the library (and you should!), you are required to write your own Module file to clean up their mess. (Yeah, you are doing the work for the library authors).
To truly achieve cross platform usage, you should write a Findrplidar.cmake module file to find the libraries for you.
To write a reasonable module file, you would most likely use API find_path for header files and find_library for libs. You should check out its docs and try using them, and maybe Google a few tutorials.
Here is my version of Findglog.cmake for your reference. (glog authors have updated their code and supports Config mode. Unfortunately, Ubuntu build doesn't use it, so I still have to write my own file)
find_path(glog_INCLUDE_DIR glog/logging.h)
message(STATUS "glog header found at: ${glog_INCLUDE_DIR}")
find_library(glog_LIB glog)
message(STATUS "libglog found at: ${glog_LIB}")
mark_as_advanced(glog_INCLUDE_DIR glog_LIB)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(glog REQUIRED_VARS
glog_INCLUDE_DIR
glog_LIB
)
if(glog_FOUND AND NOT TARGET glog::glog)
add_library(glog::glog SHARED IMPORTED)
set_target_properties(glog::glog PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
IMPORTED_LOCATION "${glog_LIB}"
INTERFACE_INCLUDE_DIRECTORIES
"${glog_INCLUDE_DIR}"
)
endif()
And you can use it like this:
find_package(glog)
target_link_libraries(main PRIVATE glog::glog)
Long answer:
The history of developers using cmake is an absolute nightmare. The internet is filled with bad practice/examples of how not to use cmake in your project, including the old official cmake tutorial (which still might be there). Mostly because no one really gives a **** (If I can build my project, who cares if it's cross platform). Another valid reason is that cmake documentations are really daunting to beginners.
This is why I am writing my own answer here, lest you get misguided by Googling elsewhere.
The nightmare is no more. The wait has ended. "The Messiah" of cmake (source) is come. He bringeth hope to asm/C/C++/CUDA projects written in 2020 and on. Here is The Word.
The link above points to the only way how cmake projects should be written and truly achieve cross platform once and for all. Note the material is not easy at all to follow for beginners. I myself spent an entire week to fully grasp what was covered in The Word, when I had become somewhat familiar with cmake concepts at the time (but lost in my old sinful ways).
The so-called "long answer" is actually shorter. It's just a pointer to the real answer. Good luck reading the Word. Embrace the Word, for anything against that is pure heresy.
Response of comment 1-5:
Good questions. A lot of those can be obtained from the Word. But the word is better digested when you become more familiar with CMake. Let me answer them in decreasing of relevance to your problem at hand.
For the ease of discussion, I'll just use libfoo as an example.
Let's say you always wants to use libfoo like this:
find_package(foo)
target_link_libraries(your_exe ... foo::foo)
Pretend foo is installed at the following location:
- /home/dev/libfoo-dev/
- include
- foo
- foo.h
- bar.h
- ...
- lib
- libfoo.so
- share
- foo/foo-config.cmake # This may or may not exist. See discussion.
Q: Only one .h file. Why?
A: Because in the case of libfoo (also true for glog), only one search of header location is necessary. Just like the example from libfoo,
where foo/foo.h and foo/bar.h are at the same location. So their output of find_path would be the same: /home/dev/libfoo-dev/include.
Q: Why I'm getting NOTFOUND for my headers and libs?
A: The function find_path and find_library only search locations specify in the documentations. By default they search system locations,
like /usr/include and /usr/lib respectively. Refer to the official docs for details on system locations. In the case of libfoo, however,
they reside in /home/dev/libfoo-dev. So you must specify these locations in cmake variable CMAKE_PREFIX_PATH. It's a ; seperated string.
One would do cmake -D CMAKE_PREFIX_PATH="/home/dev/libfoo-dev;/more/path/for/other/libs/;...;/even/more/path" .... on the command line.
One very important note: unlike Unix command find, find_path will only search specific paths inside /home/dev/libfoo-dev, not all the way down:
include (usually also include/{arch} where {arch} is sth like x86_64-linux-gnu for x86 Linux) for find_path; lib variant for find_library,
respectively. Unusual locations would require passing in more arguments, which is uncommon and most likely unnecessary.
For this very reason, for libfoo, calling find_path(... foo.h ...) is undesired. One would want find_path(... foo/foo.h ...). Refer to the docs
for more details. You can also try out yourself.
Also for this reason, it is desirable to organize libraries in the usual bin include lib share quad on Unix-like systems. I'm not familiar with Windows.
Q: Debug & Release
A: There are several options. The easiest one might be:
Prepare rplidar debug and release build in two different folders, /path/to/debug & /path/to/release for instance
Passing to Debug & Release build respectively (cmake -D CMAKE_PREFIX_PATH="/path/to/debugORrelease" ....)
There are definitely others ways, but perhaps requires special care in your Findrplidar.cmake script (maybe some if statements).
Q: Why glog::glog rather than glog?
A: It's just modern cmake practice, with small benefits. Not important right now. Refer to the Word if you are interested.
Q: You mentioned that you are writing rplidarConfig.cmake. Instead you should rename the file to Findrplidar.cmake.
A: CMake philosophy is as such:
Library authors should write foo-config.cmake or fooConfig.cmake
When they fail to provide one, it sucks. And according to the Messiah, it should be reported as a bug.
In this case, you as library user, should write Findfoo.cmake by guessing how to describe the dependencies for libfoo. For simple libraries, this is not so bad. For complex ones, like Boost, this sucks!
A few side note on this topic:
Note how Findfoo.cmake is written by library users, from guessing.
This is insane! Users shouldn't do this. This is the authors' fault, to put their users in this uncomfortable situation.
A foo-config.cmake file is extremely easy to write for authors of libfoo, IF they follow the Word exactly.
Extremely easy for the authors in the sense that: cmake can take care of everything. It will generate scripts automatically for the authors to use in their foo-config.cmake file.
Guaranteed to be cross-platform and easy to use by the users, thanks to cmake.
However, the reality sucks. Now you have to write Findfoo.cmake
Q: Why only find_package & target_link_libraries?
A: This is what the Word says. It's therefore good practice. Why the Word says so is something you have to find out yourself.
It's not possible for me to explain the gist of the Word in this answer, nor would it be convincing to you. I would just say the following:
It's very easy to write spaghetti CMakeLists that are next to impossible to maintain. The spirit of the Word helps you avoid that by
forcing you to carefully think about:
library structure: public vs private headers, for example. This makes you think about what to include in your headers and public APIs.
build specification: what is necessary to build a library you write (what to include; what to link)
usage requirement: what is necessary for others to use a library you write (what to include; what to link)
dependencies: what is the relationship of the library you write & its dependencies
Maybe more
If you think about it, these aspects are crucial to writing a cross-platform and maintainable library.
include_directories, link_directories and add_definitions are all very bad practice
(according to lots of sources, including the official documentations of these APIs). Bad practice tends to obscure the aspects above,
and causes problems later on when everything gets integrate together as a whole. E.g. include_directories will add -I to compiler for every
target written in the directory of that CMakeLists.txt. Read this sentence a few times and Spock will tell you it's illogical.
Don't worry. It's okay for now to use them when you are not familiar with the Word (Why else would this be in the last section). Once you know the Word, refactor your CMakeLists when you have time. Bad practice might cause problem later on, when your project becomes more complex. (In my professional experience, 5 very small groups of people is enough to cause a nightmare. By nightmare I mean hard code everything in CMakeLists; Create a git branch for every single different platform/device/environment; Fixing a bug meaning to cherry-pick one commit to each branch. I've been there before knowing the Word.)
The practice of the Word very well utilize the philosophy of modern CMake, to encapsulate build specifications and usage requirements inside
CMake targets. So when target_link_libraries is called, these properties gets propagated properly.

Build protoc for C++ with CMake

I'm currently working on a C++ project that reference gRPC as a git submodule and I'm using CMake to compile the dependencies and my sources. For that I basically have this in my CMakeLists.txt:
ADD_SUBDIRECTORY(lib/grpc)
Then I run:
make grpc_cpp_plugin
make my_project
Even though I specify cpp_plugin here, when it's time to compile protoc I'm actually compiling for all the languages supported, eg (Java, Csharp, ...) :
/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc.o
/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc.o
/src/google/protobuf/compiler/java/java_context.cc.o
/src/google/protobuf/compiler/java/java_doc_comment.cc.o
After looking around for some info on how to build protoc only for C++, I found that someone opened an issue on the github protobuf directory (link). However, it doesn't seem to give a clear answer.
Is there a 'clean' way to only compile the c++ dependency here ?
After doing tons of grep in gRPC's CMake files I finally compiled only the c++ version of protoc, protobuf and gRPC. And I did it in 3 steps:
go to grpc/third_party/protobuf/cmake/libprotoc.cmake and remove the lines including csharp, java, ruby, ... (Be careful to keep cpp and the langage agnostic ones)
go to grpc/CMakeLists.txt and you should be able to find this:
add_library(grpc_plugin_support
src/compiler/cpp_generator.cc
src/compiler/csharp_generator.cc
src/compiler/node_generator.cc
src/compiler/objective_c_generator.cc
src/compiler/php_generator.cc
src/compiler/python_generator.cc
src/compiler/ruby_generator.cc
)
so remove what's not needed.
and finally, grpc/third_party/protobuf/src/google/protobuf/compiler/main.cc and remove all the references to the other langage.

Can I manually use CMake's cpp file dependency-scanner in my cmake code?

I am trying to add a custom target with CMake that executes one command for each given .cpp file. The command should only be re-executed when the source file itself or one of the included source files changes. AFAIK to achieve this I need a list of all the included files and add them to the DEPENDS option of the add_custom_command() calls that belong to my custom target.
So is there a built-in way to get that list of included files?
I know about the IMPLICIT_DEPENDS option of the add_custom_command() function but it only works for Makefile generators. I would like to make this work for all generators.
Thank you for your time
Edit:
As requested I will post some cmake code to show what I want to achieve.
I want to add a custom target, that runs clang-tidy on all the given .cpp files. When incrementally building the custom target the clang-tidy commands should be re-run whenever a .cpp file or one of its directly or indirectly included header files is changed. Just like re-runs of the compiler are handled.
# ----------------------------------------------------------------------------------------
# mainTargetName The name of the target that shall be analyzed
# files A list of all the main targets .cpp files
#
function( addStaticAnalysisTarget mainTargetName files )
set(targetName runStaticAnalysis_${mainTargetName})
set(command "clang-tidy-4.0 -checks=* -p ${CMAKE_BINARY_DIR}")
foreach( file ${files} )
get_filename_component( baseName ${file} NAME_WE)
set(stampFile ${CMAKE_CURRENT_BINARY_DIR}/analyze_${baseName}.stamp )
set(fullFile ${CMAKE_CURRENT_SOURCE_DIR}/${file})
set(commandWithFile "${command} ${fullFile}")
separate_arguments_for_platform( commandList ${commandWithFile})
add_custom_command(
OUTPUT ${stampFile}
DEPENDS "${fullFile}"
IMPLICIT_DEPENDS CXX "${fullFile}"
COMMAND ${commandList}
COMMAND cmake -E touch "${stampFile}" # without creating a file as a touch-stone the command will always be re-run.
WORKING_DIRECTORY ${CPPCODEBASE_ROOT_DIR}
COMMENT "${commandWithFile}"
VERBATIM
)
list(APPEND stampFiles ${stampFile})
endforeach()
set_source_files_properties(${stampFiles} PROPERTIES GENERATED TRUE) # make the stamp files known to cmake as generated files.
add_custom_target(
${targetName}
DEPENDS ${stampFiles}
)
endfunction()
The problem with that is, that it does not seem to work. When I change included files clang-tidy is not re-run for the affected files.
I used the "Unix Makefile" generator for this example so it should work at least with make. Any hints why it doesn't?
My hopes where that I could achieve the desired behavior for all generators by somehow getting the file-dependencies at cmake time and then adding them to the ''''DEPENDS'''' list. But the dependency scanning must be done each time the command is run, so it can not be done at cmake time. This means that the scanning must be implemented by cmake which it currently is not.
A guy with similar problems:
https://gitlab.kitware.com/cmake/cmake/issues/16830
Edit 2:
I think the problem that the IMPLICIT_DEPENDS option was not working was because I did not use correct filenames. I changed that in the code snipped, but I have not yet tested if it works in the project.
I think the answer to my question is ...
No, you can not use cmakes dependency scanner in the cmake code.
That makes sense, because this problem can not be solved at cmake time, because the dependencies of a .cpp file may change without cmake being re-run.
The problem must be solved within cmake itself at make time. This is done when using the IMPLICIT_DEPENDS option.
Also, I tried to solve a Problem that I did not really have, because at this point I can only run clang-tidy on linux anyways. However, clang-tidy may become available on windows as well and then I may have the problem again.
To sum the comments up:
Tambre stated that CMake is not a compiler and therefore can not do that.
I think this is wrong. According to this article, CMake can parse cpp include dependencies because make has no such dependency searcher itself. That was news to me, but I mostly live on Windows so I am not that familiar with make. It could also be possible that in the meantime make was extended to do its own dependency searching. Also this explains why the IMPLICIT_DEPENDS option is only available for make.
Florian pointed out that it is not necessary to create an own custom target for running clang-tidy. Instead, one can use the CXX_CLANG_TIDY target property to run clang-tidy for each file after compiling it. This means however, that static-analysis can not be separated from the build which could lead to inacceptable buildtimes.
There is the cmake -E cmake_depends command line, that could be used to retrieve dependencies at cmake time. But as stated above, I erroneously thought that I needed the dependencies at cmake time, while I needed them at runtime.
The IMPLICIT_DEPENDS options did not work because I had an error in my cmake code.

CMake: compilation speed when including external makefile

I have a c++ cmake project. In this project I build (among other) one example, where I need to use another project, call it Foo. This Foo project does not offer a cmake build system. Instead, it has a pre-made Makefile.custom.in. In order to build an executable that uses Foo's features, one needs to copy this makefile in his project, and modify it (typically setting the SOURCES variable and a few compiler flags). Basically, this Makefile ends up having the sources for your executable and also all the source files for the Foo project. You will not end up using Foo as a library.
Now, this is a design I don't like, but for the sake of the question, let's say we stick with it.
To create my example inside my cmake build I added a custom target:
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/Makefile.custom.in Makefile.custom)
ADD_CUSTOM_TARGET(my_target COMMAND $(MAKE) -f Makefile.custom
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
This works. I can specify some variables to cmake, which get resolved in the call to CONFIGURE_FILE, and I end up with a working Makefile.custom. Then, invoking make my_target from the build directory, I can build the executable. I can even add it to the all target (to save me the effort of typing make my_target) with
SET_TARGET_PROPERTIES(my_target PROPERTIES EXCLUDE_FROM_ALL FALSE)
Sweet. However, cmake appears to assign a single job to the custom target, slowing down my compilation time (the Foo source folder contains a couple dozens cpp files). On top of that, the make clean target does not forward to the custom makefile. I end up having to add another target:
ADD_CUSTOM_TARGET(really-clean COMMAND "$(MAKE)" clean
COMMAND "$(MAKE)" -f Makefile.custom clean
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
which, unlike my_target with all, I can't include in the clean target (can I?).
Now, I know that a cleaner solution would be to have the Foo project be built as an external project, and then link to it. However, I've been 'recommended' to use their Makefile.custom.in makefile, modifying the few lines I need (adding my sources, specifying compiler flags, and few other minor modifications). So, regardless of how neat and clean this design pattern is, my questions are:
is there a way to tell cmake that make should use more than 1 job when making the target my_target?
is there a cleaner way to include a pre-existing makefile in a cmake project? Note that I don't want (can't?) use Foo as a library (and link against it). I want (need?) to compile it together with my executable using a makefile not generated by cmake (well, cmake can help a bit, through CONFIGURE_FILE, by resolving some variables, but that's it).
Note: I am aware of ExternalProject (as suggested also in this answer), but I think it's not exactly what I need here (since it would build Foo and then use it as a library). Also, both my project and Foo are written exclusively in C++ (not sure this matter at all).
I hope the question makes sense (regardless of how ugly/annoying/unsatisfactory the resulting design would be).
Edit: I am using cmake version 3.5.2
First, since you define your own target, you can assign more cores to the build process for the target my_target, directly inside your CMakeLists.txt.
You can include the Cmake module ProcessCount to determine the number of cores in your machine and then use this for a parallel build.
include(ProcessorCount)
ProcessorCount(N)
if(NOT N EQUAL 0)
# given that cores != 0 you could modify
# math(EXPR N "${N}+1") # modify (increment/decrement) N at your will, in this case, just incrementing N by one
set(JOBS_IN_PARALLEL -j${N})
endif(NOT N EQUAL 0)
and when you define your custom target have something like the following:
ADD_CUSTOM_TARGET(my_target
COMMAND ${CMAKE_MAKE_PROGRAM} ${JOBS_IN_PARALLEL} -f Makefile.custom
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
by the way, I don't think there's the need for you to include also CMAKE_BUILD_TOOL among the COMMANDs in your target.
I believe that instead of modifying the lines as above, you could call
make -j8 my_target
and it might start 8 jobs (just an example) without modifying the CMakeLists.txt, but I cannot guarantee this works having defined the COMMAND the way you have, just try if that's enough.
For the second point, I cannot think right now of a "cleaner" way.

How do I add objects with a custom extension to a cmake library?

I'd like to add some object files to a CMake static library, but they have a custom extension.
Here's what I've tried:
set(SRCS testfile.cxx jsobj.js)
add_library(testlib STATIC ${SRCS})
When made, CMake invokes ar testfile.cxx.o (ie the other file is completely ignored). How do I get it included in the archive? Here are some other tricks I've tried:
list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS js)
list(APPEND CMAKE_C_SOURCE_FILE_EXTENSIONS js) # no luck
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/jsobj.js.o
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/jsobj.js
${CMAKE_CURRENT_BINARY_DIR}/jsobj.js.o
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/jsobj.js.o) # still no luck
(In case you're interested, I'm using the emscripten compiler, which can accept C/C++ files as source input, and JavaScript files are essentially "precompiled objects". I want to find a way to get CMake to add them to the ar commandline, that's all!)
For the record, this is how I solved my problem in a hacky way: "proper" solutions would be gladly accepted.
I made up a new file extension for my special pre-compiled objects, "jso", then added it to the list of input files CMake understands:
list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS jso)
Then, I add my object files with the extension ".jso" to the CMake sources for inclusion in a static library target.
Finally, I hacked the compiler by setting CC=mycc, where mycc is a Python script which checks if the input has the extension ".jso": if not, it simply re-invokes the standard compiler; otherwise it copies the input to the output with no changes at all, so that mycc -c input.jso -o output.jso.o is just a file copy.
This isn't pretty, but it picks up all the dependencies perfectly for incremental builds. I can't pretend it's pretty, but doing things the way CMake likes seems to work. Here, we're just pretending all inputs are source files, even if they're actually already compiled.