How can I get FetchContent to download to a specific location? - cmake

Following the FetchContent documentation, e.g. using something like
FetchContent_Declare(
gitache_package_libcwd_r
GIT_REPOSITORY "https://github.com/CarloWood/libcwd.git"
GIT_TAG "master"
)
FetchContent_MakeAvailable(
gitache_package_libcwd_r
)
The source code is cloned into ${CMAKE_BINARY_DIR}/_deps/gitache_package_libcwd_r-src/.
How can I make it put the source code elsewhere, like /opt/gitache/libcwd_r/src/gitache_package_libcwd_r (as it would be when I'd be using ExternalProject with a PREFIX of /opt/gitache/libcwd_r)?

In case anyone stumbles on this question looking for an answer, I found that at least it is possible to replace the "${CMAKE_BINARY_DIR}/_deps" part by setting FETCHCONTENT_BASE_DIR before the call to FetchContent_Declare. I'm not sure if more fine tuned manipulation is possible or not. It seems possible, if you use the extended version of FetchContent_Populate, but using that has several drawbacks imho.
For example
set(FETCHCONTENT_BASE_DIR "/opt/gitache/libcwd_r")
FetchContent_Declare(... etc (see question)
will clone into /opt/gitache/libcwd_r/gitache_package_libcwd_r-src/ and use
/opt/gitache/libcwd_r/gitache_package_libcwd_r-build as build directory.

Related

What is the best way to flush precompiled perl6 modules?

I am trying to refactor some code. My approach (using vi) is to copy my old libraries from /lib to /lib2. That way I can hack out big sections, but still have a framework to refactor.
So I go ahead and change mymain.p6 header from use lib '../lib'; to use lib '../lib2';. Then I delete a chunk of the lines in ../lib2/mylibrary.pm6 and make darn sure :w is doing what I expect.
Imagine my surprise when my program still works perfectly despite having been largely deleted. It even works when I rm -R /lib, so nothing back there is persisting.
Is there a chance that I have a precomp of the old lib module lying around? If so, how can I flush it?
This is Rakudo Star version 2019.03.1 built on MoarVM version 2019.03
implementing Perl 6.d.
Precompiled modules are stored in the precomp directory. You can try to rename or delete the ~/.precomp directory.
See also this SO question here.
Update. Well I thought I'd replicated the scenario. It was reliably showing the bug during a one hour period. But now it isn't. Which is pretty disturbing. Investigation continues...
I've replicated #p6steve's scenario in case someone wishes to report this as a bug. At the moment I'm with #p6steve (per comment below) in that I'm going to treat this as a DIHWIDT rather than a reportable bug. That said, now we have a golf'd summary.
Original main program using path1 followed by the module it uses directly and then the one that uses:
use lib 'path1';
use lib1;
say $lib1::value;
unit module lib1;
use lib2;
our $value = $lib2::value;
unit module lib2;
our $value = 1;
This displays 1.
If the libs are copied to a fresh directory, including the .precomp directory, and then the lib2 is edited but the lib1 is not, the change to lib2 is ignored.
Here it is on glot.io before and after copying the libs and their .precomp directory and then editing the libs.
Original answer
Thank you for editing your question. That gives us all more to go on. :)
I'd like to try to get to the bottom of it and hope you're willing to have a go too. This (n)answer and comments below it will record our progress.
From your comment on #ValleLukas' answer:
Then I noticed ../lib2/.precomp directory - so realised library precomps are stored in the library folder. That did the job!
Here's my first guess at what happened:
You copied lib en masse to lib2. This copied the precomp directory with it.
You modified the use lib ... statement in mymain.p6 to refer to lib2.
Your mymain.p6 code includes a use module-that-directly-or-indirectly-uses-mylibrary.
You modify mylibrary.pm6.
But nothing changes! Why not?
You haven't touched module-that-directly-or-indirectly-uses-mylibrary, so Rakudo uses the precompiled version of that module from the lib2/.precomp directory.
Speculating...
Perhaps the fact that that precompiled version exists leads the precompilation logic to presume that if it also finds a precompiled version of a module that's used by module-that-directly-or-indirectly-uses-mylibrary then it can go ahead and use that and not even bother to check how its timestamp compares to the source version.
Does this match your scenario? If not, which bits does it get wrong?

How to remove definitions per target in cmake 2.8.12

I am using cmake 2.8.12.
I am using multiple targets with the same definitions by calling add_definitions().
I want to find out how to remove those definitions for single target and replace them by some other definitions or by default definitions like I have not called add_definitions().
I found a solution there:
https://gitlab.kitware.com/cmake/cmake/issues/19796
This is a way to remove the NOMINMAX define:
get_target_property(defs someTarget COMPILE_DEFINITIONS)
list(FILTER defs EXCLUDE REGEX [[^NOMINMAX$]])
set_property(TARGET someTarget PROPERTY COMPILE_DEFINITIONS ${defs})
The better approach here is to add the definitions for single targets rather than globally.
To do so, you should use target_compile_definitions instead of add_definitions
For instance, instead of
add_definitions(-DSOMEMACRO)
add_executable(myExecutable main.cpp)
you would use
add_executable(myExecutable main.cpp)
target_compile_definitions(myExecutable PUBLIC -DSOMEMACRO)
This allows you for a fine-grain control of the definitions, and is usually the preferred way of setting them.
I would argue that adding definitions for every target is easier than removing definitions from some of the targets.
This is a very important thing to be able to do when building large projects and using other 3rd party (e.g. from Github) projects in your own, as they often screw up the compile definitions and end up creating build-breaking problems that require you to selectively remove a definition, without editing the original project itself.
I haven't found a modern, per target way to do this sadly.
However, remove_definitiions is an old way to do it. It works in the sloppy old style of applying to the current subdirectory and below. This causes leakages to your other targets in the same directory frustratingly enough. But sometimes that might be exactly what you want.
One ugly solution is to break out part of your CMakeLists.txt into a separate CMakeLists.txt for the offending targets, and place remove_definitions only in that secondary CMakelists.txt in a subdirectory that quarantines those targets.
Hopefully CMake will add a target_remove_definitions() function.
Here is an example of where I needed this and how I solved it:
# main_directory/CMakeLists.txt
# Add subdir of the offending targets
add_subdirectory(evil_dependencies)
....
# main_directory/evil_dependencies/CMakeLists.txt
# This is required or else, there are headers in the repo
# that #define NOMINMAX which then causes a warning:
# macro redefinition, and warnings as errors = stop the build.
if(MSVC)
remove_definitions(/DNOMINMAX)
endif()
add_subdirectory(some_evil_dependency1)
add_subdirectory(some_evil_dependency2)
For GCC style problems it will look more like remove_definitions(-DSOMEDEFINE). Note, for this old style call, the /D or -D are required, unfortunately. This sadly requires you to write a bunch of extra if-then branches to see if you're in MSVC et. al. or GCC/Clang.
EDIT: See Remi's answer below. It's probably? better than mine, and how I think I'd do it now, mainly. My answer is still useful potentially for some situations where you actually want to remove definitions from a bunch of children folders as well, but Remi's answer is likely to be more elegant most of the time, esp. because of the regex that can make it easier to scan for -D and /D options.
As this is an open issue for CMake, it will likely be fixed any time, obsoleting these answers for newer versions of CMake. That hasn't happened yet (as of 2020-07-16). https://gitlab.kitware.com/cmake/cmake/-/issues/19796

where is the list of names that cmake reserves?

Everything is in the title, but for more context informations:
I am creating a library, where all components are independent (it's only because it's easier to manage 1 git repo, really).
In that library's root folder, I have 1 sub-folder for each part of the library's components, with exactly 3 "interesting folders" (src,tests,include/components_name). I have hardcoded those folders in a foreach loop so that all actions will be done for all modules by default.
The problem seems to be that, one of the modules is named "option_parser" which is, indeed, relatively generic, and also seems to be "reserved" by cmake, and same for everything derived from it. I've tried "option_parser_test", "option_parser_tests", and other random names based on "option_parser_" root.
So, here is my question: where I can learn how to avoid names that cmake reserves?
And how can I affect them anyway to my binaries (because, I feel like it's stupid to change a project's name because of a build system. Might be a strong enough reason to switch it.)
It's really quite simple. Use these three commands to see all reserved words:
cmake --help-command-list
cmake --help-variable-list
cmake --help-property-list
The answer of Cinder Biscuits above should probably already help you.
Additionally, you should probably read CMake's own documentation regarding the CMake language and in particular the note in the "Variables" section:
Note: CMake reserves identifiers that:
begin with CMAKE_ (upper-, lower-, or mixed-case), or
begin with _CMAKE_ (upper-, lower-, or mixed-case), or
begin with _ followed by the name of any CMake Command.

CMake does not find CxxTest package

I wrote the following CMakeLists.txt in order to build a tester using CxxTest (it's almost the standard example provided by FindCxxTest):
cmake_minimum_required(VERSION 2.8)
project(tester)
set(CMAKE_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
find_package(CxxTest REQUIRED)
if(CXXTEST_FOUND)
include_directories(${CXXTEST_INCLUDE_DIR})
enable_testing()
CXXTEST_ADD_TEST(tester_executable runner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/myTestsuite.h)
endif()
The problem is that CxxTest is not found although I have the folder cxxtest and the file cxxtest/TestSuite.h inside the directory where CMakeLists.txt exists.
I already looked into the source code of FindCxxTest.cmake to see how far it gets, but it doesn't even find the path CXXTEST_INCLUDE_DIR.
Do I have to set another search path or something? I'm testing on Windows.
find_path does not search the current list directory. That is, just because a relative path is reachable from the current CMakeLists.txt, does not mean that it will be found. You can find a complete description of the search order in the manual.
A quick and dirty solution is to add the respective directory to your CMAKE_PREFIX_PATH:
set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR})
find_package(CxxTest)
More fine grained control is available via the CMAKE_SYSTEM_PREFIX_PATH, CMAKE_INCLUDE_PATH, CMAKE_LIBRARY_PATH and CMAKE_PROGRAM_PATH variables. Also, some find scripts provide means of injecting search hints without having to pollute the global variables (although FindCxxTest does not seem to offer this).
Another option is, if you anyway include the CxxTest sources at a fixed place in your source tree, to not use the the find script at all, but hardcode the paths instead.
This may feel like a dirty solution at first, but if you can really rely on the sources always being there, it's actually the cleanest and most robust way to solve this. Find scripts really only make sense when you can not say where exactly on the system the files are located.

Can CMake recognize CMakeLists.txt with another name (CMakeLists_nightly.txt)?

I am wanting to create CMakeLists.txt files that are more specifically named such as "CMakeLists_nightly.txt", "CMakeLists_weekly.txt" and so forth. The reason I want to do this is to cut down on the folder hierarchy clutter of my project. I could easily put each of these files in their own folder with the postfix I showed above but I do not want to do this.
Can I tell cmake to take a CMakeLists.txt file by another name? I have seen this question asked before on another forum (http://www.cmake.org/pipermail/cmake/2007-August/016036.html) but it was back in 2007 and the answer was no. Does the current version of CMake provide this capability?
Not really, but you can emulate this by putting CMakeLists.txt in separate directories, e.g. continous/CMakeLists.txt and nightly/CMakeLists.txt. Use INCLUDE to include the appropriate scripts for each of the build configs.
Consider if this really is the right approach - completely separating the nightly and continuous script is a really bad idea as that will lead to duplication and a very bug prone build setup.
Answer, which came into my mind, while I was reading an answer from larsmoa and thinking about it little bit longer:
(this is not exactly the answer to the question about different name for CMakeLists.txt, but rather, to "how to have two different CMake configuraiton files in the same directory")
You can avoid creating multiple directories and storing there CMakeLists.txt (it may also be problematic, if you want your script to be the parent of everything). My Idea is, that you can have two "include" cmake files with any names you like. And then in CMakeLists.txt you may have an set(CACHE), which controlls, which include-script should be actually included.
With this setup you can have two build directories: one configured with one value of the option, and another - with another. Depending on that, in which build-directory you do the build, corresponding build definition will be used.
It can look something like this:
CMakeLists.txt:
set(
MY_BUILD_KIND BUILD_A CACHE STRING
"Select build kind: BUILD_A or BUILD_B"
)
if ( MY_BUILD_KIND strequal "BUILD_A" )
include(build_a.cmake)
elseif (MY_BUILD_KIND strequal "BUILD_B")
include(build_b.cmake)
else ()
message ( FATAL_ERROR "Unknown build kind: ${MY_BUILD_KIND}" )
endif ()
Background (why do I need it?): My situation is kind of exotic, I guess. I have a C++ project, different parts of which use two different compilers. And there is a part of it, which needs to be built by each of them. So the directory structure is like this:
Projects
CompilerAProjects
CompilerBProjects
CommonProjects
Here "CommonProjects" are included as Part of "CompilerAProjects" and also as part of "CompilerBProjects". Now we try to integrate cmake and I was thinking, how can we keep the structure, but do the build with CMake. If I put CMakeLists.txt in the root directory, then I don't understand, how to differentiate between two compilers. And if I don't have the root project, then it is not clear, how to refer to "sibling" project. So I came to the idea, that I can included sub-directories basing on the current compiler. And then I decided, that actually it is not necessary, that compiler is the driving factor, we can use set(CACHE) instead. And we are not restricted to select, which sub-directory we select, but can also include ".cmake" files.