How to avoid polluting directory with CMake target logs - cmake

I have a simple project with one shared library called A and one executable called B linking A. I make a Visual Studio 2017 build just outside my sources so that the build directory and the source directory have both the same parent directory. This is fine.
But when I build my Visual Studio 2017 solution, many undesired directories appear under parent directory as well; one for each target that did run (A, B, INSTALL, etc.) that contains the build log for that target. I don't want those polluting log directories or it would be OK if they would appear under my build directory along Visual Studio 2017 stuff if they can't be avoided. Anyone knows how to handle this?
CMake version: 3.8.1
EDIT
The last 3 directories are those that are unwanted:
Parent directory
|-- build-vc15-x64 directory
|-- VS 2017 related stuff
|-- sources directory
|-- CMakeLists.txt
|-- libA sources directory
|-- stuff for libA
|-- execB sources directory
|-- stuff for execB
|-- unexpected directory here when building libA in solution in build-vc15-x64 (contains build log file of libA)
|-- unexpected directory here when building execB in solution in build-vc-15-x64 (contains build log file of execB)
|-- x64 (contains build log file of target INSTALL)

Use out-of-source builds, in other words, your build and your source directory should be different directories. Additionally, you have to call CMake and build just within your build directory, not in the parent directory. CMake creates a bunch of auxiliary files and directory right where it is called.
There is no point calling CMake in the common parent directory of source and build dir.

Related

How to set DYLD_LIBRARY_PATH from cmake for executable file?

I compiled a executable file that is linked to a some library a.dyld on Mac OS, which is located in /mylib using cmake.
When I tried to run the program, the error message comes:
dyld: library not loaded a.dyld
Referenced from: path the executable file belongs
Reason: imagh not found.
So, if I set the environment variable $DYLD_LIBRARY_PATH to /mylib, the program works correctly.
But I dont want to do that since it forces every executable files to lookup the same library. (I have multiple libraries of the same name in many directories where each directory name specifies the functionality of the library.)
Is it possible to set $DYLD_LIBRARY_PATHfrom cmake??
Say, I have a multiple directories like
test_project
|--CMakeLists.txt
|--/src
|--CMakeLists.txt (build b.dyld)
... (programs for b.dyld)
|--/run_test1
|-- CMakeLitsts.txt (link b.dyld, and a.dyld under /mylyb1)
|-- (programs to be run)
|--/run_test2
|-- CMakeLitsts.txt (link b.dyle, and a.dyld under /mylyb2)
|-- (programs to be run)
... (/run_testN)

Cannot build library in subdirectory when top-level CMakeLists.txt calls install(EXPORT)

I'm trying to add a feature as a sub-library to
an existing application. But I met troubles of install(EXPORT ...)
My project source code structure shows as below:
app (the existing application)
|-- top-level CMakeLists.txt
|
|-- sublib (my new feature)
| |-- src
| |-- include
| `-- CMakeLists.txt
|
|-- other existing src ...
I build sublib in the CMakeLists.txt inside my own feature as:
add_library(sublib ${LIB_SRC})
I modify the top-level CMakeLists.txt in the existing application to
link sublib:
add_subdirectory(subdirectory of sublib)
...
target_link_directories(app sublib)
I thought it was enough. But CMake threw out an error:
CMake Error: install(EXPORT "appTargets" ...) includes target "app"
which requires target "sublib" that is not in the export set.
I guess it is because app itself is exported by install(EXPORT .. ) in the
top-level CMakeLists.txt. Thus I also try to install and export sublib.
I add the install and export into sublib CMakeLists.txt:
install(TARGETS sublib
EXPORT sublibTargets
ARCHIVE DESTINATION ${BIN_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
RUNTIME DESTINATION ${LIB_INSTALL_DIR}
)
install(EXPORT sublibTargets
FILE sublib-config.cmake
DESTINATION ${LIB_INSTALL_DIR}/cmake/sublib
)
I then add find_package() in top-level CMakeLists.txt:
find_package(sublib REQUIRED)
target_link_directories(app sublib)
However, it becomes worse. sublib is never built at all and
sublib-config.cmake is not found.
I manually set the PATHS to sublib-config.cmake in find_package() but it still failed.
Could you please tell me how fix the EXPORT issue?
Thank you.
Best regards,
David Hu
You should not have to call find_package(sublib) in your top-level CMakeLists.txt, this is intended to be used by a project that uses sublib once it is installed. Because you call add_subdirectory(sublib) in your CMakeLists.txt, the target sublib is already available where you call target_link_directories(app sublib).
I tried to answer it by myself. I'm inspired by #piwi.
If the sublib is put under app as a sub-directory, sublib source code should be built together with those of app, rather than treating sublib as an standalone library. No need to export sublib.
Export and install of sublib is only necessary when sublib is placed as an independent library. Export and install the sublib in sublib CMakeLists.txt. Put a Findsublib.cmake under app's cmake/modules. Thus later when app CMakeLists.txt call find_package(sublib), Findsublib.cmake tells app how to find out sublib and build or link sublib

specify destination for CTestTestfile.cmake

When executing cmake to generate ctest inputs, how can I directly specify the destination directory for the cmake-generated CTestTestfile.cmake? Specifically, my test suite is an independent cmake project. I currently add it to the main cmake project with include(), but the more appropriate method is to use add_subdirectory(). However, add_subdirectory() installs CTestTestfile.cmake in the subproject's directory in the build directory, but I need it in build/ for ctest to find it.
I set up the test macros in a file CTestList.cmake which lives in the test_project. This file is included in the build in test_project/CMakeLists.txt:
include(CTest)
include(${CMAKE_CURRENT_LIST_DIR}/CTestList.cmake)
With include():
project/
|-- CMakeLists.txt
|-- src/
|-- test_project/
`-- build/
|-- CTestTestfile.cmake
`-- test_project/
With add_subdirectory():
project/
|-- CMakeLists.txt
|-- src/
|-- test_project/
`-- build/
`-- test_project/
`-- CTestTestfile.cmake
The include and the add_subdirectory commands of CMake are very different.
While the include command works like #include of C and C++ – loads the content of included file into the file where it appears –, the add_subdirectory adds a subdirectory to the build. This means that when you use the add_subdirectory the variables inside the subdirectory's CMakeLists.txt will be the part of a different scope and the value of CMAKE_CURRENT_BINARY_DIR variable will be different too. Just add the following line to the test_project/CMakeLists.txt and try either to include it or add it by add_subdirectory:
message(STATUS "The files will be generated into: " ${CMAKE_CURRENT_BINARY_DIR})
The enable_testing enables testing for current directory and below. So, when you used the add_subdirecory instead of include the current directory meant build/test_project/ – as explained above.
To make sure the CTestTestfile.cmake will be created in build directory too, simply add an extra enable_testing command to the top-level CMakeLists.txt.

include second cmake project in main project

I have a directory layout like the following
projectA/
|-- CMakeLists.txt
|-- src/
|-- main.cpp
projectB/
|-- CMakeLists.txt
|-- src/
|-- file1.cpp
|-- file1.hpp
|-- file2.hpp
|-- main.cpp
|-- third_party/
|-- include
|-- lib1
I can build my code (separately) for projectA and projectB just fine, i.e. both projects run by itself, independet of each other.
Now, in projectA I need to use code that exists in projectB (specifically file1.cpp, file1.hpp, file2.hpp and the third party libs).
It seems bad practice to me to just copy the necessary files from projectB/src, paste it into the src directory of projectA and adjust the CMakeLists.txt in projectA accordingly (by partially merging projectB/CMakeLists.txt and projectA/CMakeLists.txt).
Is there a nice way I can use CMake to (and now I'm not sure about the right terminology) include the project defined by projectB/CMakeLists.txt in projectA/CMakeLists.txt. The idea is that everything concerning projectB to run independently is stated in projectB/CMakeLists.txt and shouldn't I be able to access this information when I want to use it in projectA?
This is probably a common question, nevertheless I did not find anything helpful online, might also be due to not having the right terminology at hand.
You have to decide the level of encapsulation you need.
Package: If dependency ProjectB can run independently and you only ever need it for its compiled library, then use CMake's packaging system, i.e. export(TARGETS) or export(EXPORT) or export(PACKAGE) or install(EXPORT).
add_subdirectory: If dependency ProjectB also has build target information you need, e.g. compile defines, flags and other dependencies, then you can just make a top-level CMakeLists and use add_subdirectory()
include: If dependency ProjectB only has sub-target properties you need, including sources, you could include() the CMakeLists.txt, but this is really designed for sub directories and where you do not want to change the existing current directory for CMake processing
Interface library: If your third party libraries are not header-only, then they should probably be independent packages, otherwise assuming they are not huge like Boost, you can just copy them to ProjectA. Boost-like dependencies should almost always be kept external to projects
Hardcode paths: You could hardcode paths to the individual files of projectB, but this is brittle without making it a subdirectory of projectA, which in turn would offer better solutions, as above
Refactor to third library: If none of the above fits, you could refactor out the specific files as a separate library and use the standard packaging mechanism to depend on it for both ProjectA and ProjectB.
You can use ExternalProject module
https://cmake.org/cmake/help/v3.7/module/ExternalProject.html
Suppose, projectB is library. Then:
project("A")
include(ExternalProject)
ExternalProject_Add(b_lib
SOURCE_DIR "${B_SOURCE_DIR}"
BINARY_DIR "${B_BUILD_DIR}"
CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-DCMAKE_INSTALL_PREFIX=${B_INSTALL_DIR}"
"-DARBITRARY_VAR=some_value")
add_executable(a_exe src/main.cpp)
target_include_directories(a_exe PRIVATE "${B_INSTALL_DIR}")
target_link_libraries(a_exe "${B_INSTALL_DIR}/b_lib")

developing an llvm pass with cmake out of llvm source directory

I am trying to develop an llvm pass under my project directory. For that, I follow the info in http://llvm.org/docs/CMake.html#developing-llvm-pass-out-of-source. I create my CMakeFiles appropriately as in this link and my final project directory is like;
|-- src
| |-- CMakeLists.txt
| |-- bigForPass
| | |-- CMakeLists.txt
| | |-- bigForPass.cpp
| | |-- merged.bc
| |-- build
I also linked my source files with llvm root directory without any problem.
Finally I make the build under the 'build' folder and my shared library is created successfully with no problems (under build/bin folder) with the name LLVMHello1.dylib.
However, when I try to run my pass over merged.bc file (which contains my llvm code) with the command
opt -load ../build/bin/LLVMHello1.dylib -bishe_insert <merged.bc> final.bc
I keep getting the error;
Error opening '../build/bin/LLVMHello1.dylib': dlopen(../build/bin/LLVMHello1.dylib, 9): Symbol not found: __ZTIN4llvm10ModulePassE
Referenced from: ../build/bin/LLVMHello1.dylib
Expected in: flat namespace
in ../build/bin/LLVMHello1.dylib
-load request ignored.
Any ideas and suggestions on this appreciated ?
Thanks a lot in advance.
from http://www.jiang925.com/node/28
Undefined Symbol: _ZTIN4llvm12FunctionPassE There is an inconsistency
between LLVM main build system and the cmake support for building
out-of-source. The LLVM binaries are built without runtime type info
"-fno-rtti". Therefore, the out-of-source passes have to be built the
same way otherwise opt will complain that symbol
"_ZTIN4llvm12FunctionPassE" is undefined.
To solve this problem, LLVM must be compile with RTTI enabled. Add
"-DLLVM_REQUIRES_RTTI=1" to cmake, or add "REQUIRES_RTTI=1" to make.
So I added SET(CMAKE_CXX_FLAGS "-Wall -fno-rtti") to CMakeLists.txt of my pass library and then it's working.