CMake define new target by string processing existing $<TARGET_FILE> - cmake

I"m trying to modernize an older CMake script that essentially does the following to generate a libtool file:
get_target_property(target_location ${target} LOCATION)
get_filename_component(target_we ${target_location} NAME_WE)
get_target_property(target_deps ${target} LT_DEPENDENCY_LIBS)
# ...
# Get a bunch more properties...
# ...
set(la_target ${PROJECT_BINARY_DIR}/${target_we}.la)
# ...
# Do a bunch of file(WRITE...) file(APPEND...) etc
# ...
install(FILES ${la_target} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
You cannot get the LOCATION property from a target in modern cmake, and I can't figure out how to do get_filename_component() on a $ generator.
Using the generator in an add_custom_command() COMMAND statement only allows one line, so I can't set variables to do all the necessary get_target_property()/file(WRITE...) processing.
Alternatively I can add a COMMAND cmake -P script.cmake to run a script which can do all the string processing but can't define or reference targets, so I appear to be stuck.
EDIT: I'm using the Makefile generator, on macOS, the target in question is a shared library that's generated in the same project.
EDIT2: The error is:
The LOCATION property may not be read from target "mytarget".
Use the target name directly with add_custom_command, or use
the generator expression $<TARGET_FILE>, as appropriate.

You can to it like this:
first use file command to expand generator expressions and render a level-2 template
... which is going to be rendered at build time by configure_file
Here is a sample project:
cmake_minimum_required(VERSION 3.10)
project(location-test VERSION 0.0.1 LANGUAGES CXX)
add_executable(foo foo.cc)
file(GENERATE OUTPUT blah.la.in INPUT blah.la.in.in)
configure_file(render-variables.cmake.in render-variables.cmake #ONLY)
add_custom_command(
OUTPUT "${PROJECT_BINARY_DIR}/blah.la"
COMMAND "${CMAKE_COMMAND}"
-DPROJECT_BINARY_DIR="${PROJECT_BINARY_DIR}"
-DPROJECT_NAME="${PROJECT_NAME}"
-DPROJECT_VERSION="${PROJECT_VERSION}"
-P "${PROJECT_BINARY_DIR}/render-variables.cmake"
MAIN_DEPENDENCY "${PROJECT_BINARY_DIR}/blah.la.in"
DEPENDS "${PROJECT_BINARY_DIR}/render-variables.cmake"
)
add_custom_target(
make-la-la-la ALL
DEPENDS "${PROJECT_BINARY_DIR}/blah.la"
)
blah.la.in.in (2-levels of tempaltes %):
# This file going to be rendered by the following pipeline:
# - at CMake execution time it'll expand all generator expressions
# (e.g. $<TARGET_FILE:foo>)
# - at build time, the `render-variables.cmake` script will substitute
# CMake variables (like #PROJECT_NAME# or #PROJECT_VERSION#)
write the template for your real .la file... render-variables.cmake.in is trivial as :
configure_file("${PROJECT_BINARY_DIR}/blah.la.in" "${PROJECT_BINARY_DIR}/blah.la" #ONLY)
And finally a dummy C++ file foo.cc:
#include <iostream>
int main()
{
std::cout << "Hello Africa!\n";
}
Build it!
localtion-sample$ mkdir build/
localtion-sample$ cd build/
localtion-sample/build$ cmake ..
-- The CXX compiler identification is GNU 5.4.0
-- Check for working CXX compiler: /usr/x86_64-pc-linux-gnu/gcc-bin/5.4.0/c++ -- works
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/localtion-sample/build
localtion-sample/build$ make
Scanning dependencies of target foo
[ 33%] Building CXX object CMakeFiles/foo.dir/foo.cc.o
[ 66%] Linking CXX executable foo
[ 66%] Built target foo
Scanning dependencies of target make-la-la-la
[100%] Generating blah.la
[100%] Built target make-la-la-la
localtion-sample/build$ ll
total 52K
drwxr-xr-x 6 zaufi zaufi 320 Feb 9 22:35 CMakeFiles/
-rw-r--r-- 1 zaufi zaufi 287 Feb 9 22:35 blah.la
-rw-r--r-- 1 zaufi zaufi 300 Feb 9 22:35 blah.la.in
-rw-r--r-- 1 zaufi zaufi 11K Feb 9 22:35 CMakeCache.txt
-rw-r--r-- 1 zaufi zaufi 1.5K Feb 9 22:35 cmake_install.cmake
-rwxr-xr-x 1 zaufi zaufi 14K Feb 9 22:35 foo
-rw-r--r-- 1 zaufi zaufi 5.0K Feb 9 22:35 Makefile
-rw-r--r-- 1 zaufi zaufi 89 Feb 9 22:35 render-variables.cmake
localtion-sample/build$ cat blah.la
# This file going to be rendered by the following pipeline:
# - at CMake execution time it'll expand all generator expressions
# (e.g. /tmp/localtion-sample/build/foo)
# - at build time, the `render-variables.cmake` script will substitute
# CMake variables (like location-test or 0.0.1)

Related

Compiler can't find ZLIB even though it is present

I have the following settings in CLion 2020.1:
I have the following lines in my CMakeLists.txt file:
set(ZLIB_LIBRARY "C:\\Program Files (x86)\\GnuWin32")
set(ZLIB_INCLUDE_DIR "C:\\Program Files (x86)\\GnuWin32\\include")
find_package(ZLIB REQUIRED)
find_package (ZLIB)
if (ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIR})
endif (ZLIB_FOUND)
And, the compiler generates the following error:
C:\Users\pc\CLionProjects\myproject\src\utils/io_utils.hh(8,10): fatal error: 'zlib.h' file not found
#include <zlib.h>
^~~~~~~~
11 warnings and 1 error generated.
NMAKE : fatal error U1077: 'C:\PROGRA~1\LLVM\bin\clang-cl.exe' : return code '0x1'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
How can I correct this?
You only need the following line:
find_package(ZLIB REQUIRED)
# To use zlib:
add_executable(main main.cpp)
target_link_libraries(main PRIVATE ZLIB::ZLIB)
Then, at the command line, pass "-DCMAKE_PREFIX_PATH=C:/Program Files (x86)/GnuWin32" as an argument to the CMake configure step. CMAKE_PREFIX_PATH may also be set as an environment variable and is formatted like your system's PATH env-var (so ; separators on Windows and : elsewhere).
The variable CMAKE_PREFIX_PATH is consulted for a list of sysroots by the find_* commands. The directories in this variable should contain subdirectories like include, lib, bin, etc. Read more about the CMake search procedure here: https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure
So you can see exactly what I did from the x64 Native Tools Command Prompt for VS 2019:
D:\>dir "C:\Program Files (x86)\GnuWin32"
Volume in drive C has no label.
Volume Serial Number is B854-7CB4
Directory of C:\Program Files (x86)\GnuWin32
05/26/2021 11:40 AM <DIR> .
05/26/2021 11:40 AM <DIR> ..
05/26/2021 11:40 AM <DIR> bin
05/26/2021 11:40 AM <DIR> contrib
05/26/2021 11:40 AM <DIR> doc
05/26/2021 11:40 AM <DIR> include
05/26/2021 11:40 AM <DIR> lib
05/26/2021 11:40 AM <DIR> man
05/26/2021 11:40 AM <DIR> manifest
05/26/2021 11:40 AM <DIR> uninstall
0 File(s) 0 bytes
10 Dir(s) 204,769,185,792 bytes free
D:\>dir "C:\Program Files (x86)\GnuWin32\lib"
Volume in drive C has no label.
Volume Serial Number is B854-7CB4
Directory of C:\Program Files (x86)\GnuWin32\lib
05/26/2021 11:40 AM <DIR> .
05/26/2021 11:40 AM <DIR> ..
07/20/2005 08:52 AM 77,534 libz.a
07/20/2005 08:50 AM 43,738 libz.dll.a
07/20/2005 08:50 AM 6,656 zlib-bcc.lib
07/20/2005 08:46 AM 1,868 zlib.def
07/20/2005 08:50 AM 14,778 zlib.lib
5 File(s) 144,574 bytes
2 Dir(s) 204,769,185,792 bytes free
D:\>mkdir test
D:\>cd test
D:\test>notepad CMakeLists.txt
D:\test>type CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(test)
find_package(ZLIB REQUIRED)
D:\test>cmake -S . -B build "-DCMAKE_PREFIX_PATH=C:/Program Files (x86)/GnuWin32"
-- Building for: Visual Studio 16 2019
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19042.
-- The C compiler identification is MSVC 19.28.29915.0
-- The CXX compiler identification is MSVC 19.28.29915.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29910/bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29910/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found ZLIB: C:/Program Files (x86)/GnuWin32/lib/zlib.lib (found version "1.2.3")
-- Configuring done
-- Generating done
-- Build files have been written to: D:/test/build
It absolutely does find ZLIB like this.

cmake add_custom_command introduces false dependency unless add_custom_target also used

I'm using cmake to build some libraries, all of which generate some of their files.
I've created the generated files using add_custom_command(), but I've discovered something which seems like a false dependency. If a downstream library has a generated file and links to an upstream library, the downstream library sources will not start to compile until the upstream library is completely built. With many libraries (more than 50) in my project, this false dependency causes serialization in the build.
What's curious is that I also noticed that if an explicit add_custom_target() for the generated file is used with add_dependencies(), the false dependency no longer exists, and the files in the downstream library will compile concurrently with the ones in the upstream library. So I have a workaround, but is this expected behavior?
Using Cmake 1.19, Ninja 1.10.2.
The following is a minimal CMakeLists.txt file that shows what happens. The WORKS option conditionally adds the add_custom_target() and add_dependencies() clauses which cause it to work (quickly). The files foo.c and bar.c are empty, and I'm building in a subdirectory of the CMakeLists.txt directory.
I put a file called /tmp/x which is a wrapper around cc that sleeps to show the serialization occur:
#!/bin/bash -e
echo "mycc" $(date)
sleep 4
exec /usr/bin/cc $*
Here is the CMakeLists.txt:
cmake_minimum_required(VERSION 3.19)
project(test)
option(WORKS "false dependency gone if WORKS set to ON" OFF)
add_library(foo
foo.c
)
add_library(bar
bar.c
bargen.h
)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_custom_command(OUTPUT bargen.h
COMMAND touch bargen.h
)
if (${WORKS})
add_custom_target(generate_file
DEPENDS bargen.h
)
add_dependencies(bar generate_file)
endif()
target_link_libraries(bar PUBLIC foo)
Build it like this and you will see the serialization: bar.c will not start to compile until after foo.c has finished compiling (in fact, not until after the foo library is built). (I'm explicitly choosing '-j 4' to ensure Ninja will try to build in parallel).
cmake -DWORKS=OFF -G Ninja -DCMAKE_C_COMPILER=/tmp/x .. && ninja clean && ninja -j 4 -v | grep mycc
This shows the following output:
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/rhb/Downloads/cmake-anomaly/build
[1/1] Cleaning all built files...
Cleaning... 5 files.
mycc Sat Jan 2 15:15:25 EST 2021
mycc Sat Jan 2 15:15:29 EST 2021
Now build it like this and you'll see that bar.c compiles concurrently with foo.c:
cmake -DWORKS=ON -G Ninja -DCMAKE_C_COMPILER=/tmp/x .. && ninja clean && ninja -j 4 -v | grep mycc
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/rhb/Downloads/cmake-anomaly/build
[1/1] Cleaning all built files...
Cleaning... 5 files.
mycc Sat Jan 2 15:15:37 EST 2021
mycc Sat Jan 2 15:15:37 EST 2021
This was reported as a cmake issue and recently fixed with a new argument to add_custom_command. This fix will be released with the next cmake version (3.27).
DEPENDS_EXPLICIT_ONLY
.. versionadded:: 3.27
Indicate that the command's DEPENDS argument represents all files
required by the command and implicit dependencies are not required.
Without this option, if any target uses the output of the custom command,
CMake will consider that target's dependencies as implicit dependencies for
the custom command in case this custom command requires files implicitly
created by those targets.
Only the Ninja Generators actually use this information to remove
unnecessary implicit dependencies.

CMake INSTALL and RENAME cannot find file

I'm trying to make and install a config.cmake file for the project that I'm building, and the install part isn't working because apparently it can't find the file. I was originally using the INSTALL command from cmake, and when that didn't work I tried file( RENAME ... ) because I have a little more experience with it - neither seem to work. I've verified that the file is being made in the correct location and with the expected filename.
This is the relevant part of the CMakeLists.txt:
################################################################################
# Build the config.cmake file for finding project information
################################################################################
file(WRITE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake "set(${PROJECT_NAME}_PROTO_DIR ${PROTO_MAIN_DIR})\n")
file(APPEND ${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake "set(${PROJECT_NAME}_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/include/;${PROTO_GEN_DIR})\n")
file(APPEND ${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake "set(${PROJECT_NAME}_LIBRARY_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/)\n")
file(APPEND ${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake "set(${PROJECT_NAME}_LIBRARIES ${PROJECT_LIBRARIES})\n")
message( "CMAKE_BINARY_DIR: " ${CMAKE_BINARY_DIR} )
message( "PROJECT_NAME: " ${PROJECT_NAME} )
#INSTALL(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake DESTINATION ~/CMake/Modules/)
file(RENAME ${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake ~/CMake/Modules/${PROJECT_NAME}Config.cmake)
Here's the relevant output when I try to rune cmake:
CMAKE_BINARY_DIR: /home/ava/workspace/frontseat_drivers/build
PROJECT_NAME: frontseat
CMake Error at src/frontseat/CMakeLists.txt:47 (file):
file RENAME failed to rename
/home/ava/workspace/frontseat_drivers/build/frontseatConfig.cmake
to
~/CMake/Modules/frontseatConfig.cmake
because: No such file or directory
and here's output confirming that the file is where I expect with the name that I expect:
ava#3b97b310abf0:~/workspace/frontseat_drivers/build$ ls -l
total 32
-rw-rw-r--. 1 ava ava 12219 Jun 13 19:04 CMakeCache.txt
drwxrwxr-x. 5 ava ava 4096 Jun 13 18:48 CMakeFiles
-rw-rw-r--. 1 ava ava 2250 Jun 13 15:41 cmake_install.cmake
-rw-rw-r--. 1 ava ava 315 Jun 14 12:30 frontseatConfig.cmake
-rw-rw-r--. 1 ava ava 6397 Jun 13 18:48 Makefile
drwxrwxr-x. 5 ava ava 98 Jun 13 18:48 src
What would cause CMake not to be able to see the file?
The error is probably about destination file ~/CMake/Modules/frontseatConfig.cmake. It is because CMake doesn't interpret ~ part, so it cannot resolve the path correctly.
Instead of ~ use $ENV{HOME} for point to the user's home directory.

ExternalProject_Add_Step ERROR add_custom_command given APPEND option with output

Using cmake version 3.7.0-rc3 on Win7, I can run the below code using ExternalProject_Add_Step no problem. But using cmake version 3.7.0 on Ubuntu16, I get the error:
add_custom_command given APPEND option with output "ExternalProjects/Stamp/boost/boost-CONFIGURE" which is not already a custom command output.
Here's simplified code that reproduces the issue.
ExternalProject_Add(
boost
URL https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.gz/download
URL_HASH MD5=6f4571e7c5a66ccc3323da6c24be8f05
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
ExternalProject_Add_Step(
boost UNIX_CONFIGURE DEPENDEES DOWNLOAD DEPENDERS CONFIGURE
WORKING_DIRECTORY "<SOURCE_DIR>" COMMAND ./bootstrap.sh
)
The culprit seems to be DEPENDERS CONFIGURE. If I take that out, then it works fine. But... I'd like to be able to specify that the step CONFIGURE depends on this custom step, and on Windows I can, but on Ubuntu I can't. Any ideas why?
I don't see it in the documentation, but you've just simply run into a case sensitivity issue. Modifying your CMakeLists.txt to:
❯ cat ../CMakeLists.txt
cmake_minimum_required(VERSION 3.7)
include(ExternalProject)
ExternalProject_Add(
boost
URL https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.gz/download
URL_HASH MD5=6f4571e7c5a66ccc3323da6c24be8f05
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
ExternalProject_Add_Step(
boost UNIX_CONFIGURE DEPENDEES download DEPENDERS configure
WORKING_DIRECTORY "boost-prefix/src/boost/" COMMAND ./bootstrap.sh
)
Notice that "download" and "configure" in ExternalProject_Add_Step() are now downcased. Now, cmake and make complete successfully.
❯ cmake ..
-- The C compiler identification is AppleClang 8.0.0.8000042
-- The CXX compiler identification is AppleClang 8.0.0.8000042
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/nega/foo/build
❯ make
Scanning dependencies of target boost
[ 11%] Creating directories for 'boost'
[ 22%] Performing download step (download, verify and extract) for 'boost'
-- verifying file...
file='/Users/nega/foo/build/boost-prefix/src/boost_1_62_0.tar.gz'
-- File already exists and hash match (skip download):
file='/Users/nega/foo/build/boost-prefix/src/boost_1_62_0.tar.gz'
MD5='6f4571e7c5a66ccc3323da6c24be8f05'
-- extracting...
src='/Users/nega/foo/build/boost-prefix/src/boost_1_62_0.tar.gz'
dst='/Users/nega/foo/build/boost-prefix/src/boost'
-- extracting... [tar xfz]
-- extracting... [analysis]
-- extracting... [rename]
-- extracting... [clean up]
-- extracting... done
[ 33%] Performing UNIX_CONFIGURE step for 'boost'
Building Boost.Build engine with toolset darwin... tools/build/src/engine/bin.macosxx86_64/b2
Detecting Python version... 2.7
Detecting Python root... /Users/nega/i3/virtenv
Unicode/ICU support for Boost.Regex?... not found.
Generating Boost.Build configuration in project-config.jam...
Bootstrapping is done. To build, run:
./b2
To adjust configuration, edit 'project-config.jam'.
Further information:
- Command line help:
./b2 --help
- Getting started guide:
http://www.boost.org/more/getting_started/unix-variants.html
- Boost.Build documentation:
http://www.boost.org/build/doc/html/index.html
[ 44%] No update step for 'boost'
[ 55%] No patch step for 'boost'
[ 66%] No configure step for 'boost'
[ 77%] No build step for 'boost'
[ 88%] No install step for 'boost'
[100%] Completed 'boost'
[100%] Built target boost
Now, look in boost-prefix/src/boost-stamp of your build directory:
❯ v boost-prefix/src/boost-stamp
total 32
drwxr-xr-x 15 nega staff 510 Dec 20 12:29 ./
drwxr-xr-x 6 nega staff 204 Dec 20 12:28 ../
-rw-r--r-- 1 nega staff 0 Dec 20 12:29 boost-UNIX_CONFIGURE
-rw-r--r-- 1 nega staff 0 Dec 20 12:29 boost-build
-rw-r--r-- 1 nega staff 0 Dec 20 12:29 boost-configure
-rw-r--r-- 1 nega staff 0 Dec 20 12:29 boost-done
-rw-r--r-- 1 nega staff 0 Dec 20 12:28 boost-download
-rw-r--r-- 1 nega staff 0 Dec 20 12:29 boost-install
-rw-r--r-- 1 nega staff 0 Dec 20 12:28 boost-mkdir
-rw-r--r-- 1 nega staff 0 Dec 20 12:29 boost-patch
-rw-r--r-- 1 nega staff 0 Dec 20 12:29 boost-update
-rw-r--r-- 1 nega staff 173 Dec 20 12:18 boost-urlinfo.txt
-rw-r--r-- 1 nega staff 4424 Dec 20 12:18 download-boost.cmake
-rw-r--r-- 1 nega staff 1611 Dec 20 12:28 extract-boost.cmake
-rw-r--r-- 1 nega staff 0 Dec 20 12:28 verify-boost.cmake
You'll notice at each step has a "file stamp" named after it. The default steps are all in lowercase, and your custom step "UNIX_CONFIGURE" is uppercase, just as you defined it. If you mix case your custom step, you'll get that as output.
❯ grep -i unix ../CMakeLists.txt
boost uNiX_CoNFiGuRe DEPENDEES download DEPENDERS configure
❯ make | grep -i unix
[ 33%] Performing uNiX_CoNFiGuRe step for 'boost'
❯ find boost-prefix/src/boost-stamp | grep -i unix
boost-prefix/src/boost-stamp/boost-uNiX_CoNFiGuRe
Also, look at the make output.
[ 22%] Performing download step (download, verify and extract) for 'boost'
[....]
[ 33%] Performing uNiX_CoNFiGuRe step for 'boost'
[....]
[ 44%] No update step for 'boost'
[ 55%] No patch step for 'boost'
[ 66%] No configure step for 'boost'
[ 77%] No build step for 'boost'
[ 88%] No install step for 'boost'
[100%] Completed 'boost'
[100%] Built target boost
All the default steps are referred to in lowercase.
Summary
In CMake's ExternalProject module, refer to default steps in lowercase.

Cmake/cpack: how to create a libc++ static library deb without headers?

I have been trying to create a deb for LLVM libc++ 3.4 on a Ubuntu 12.04LTS 64bit box tonight. I would like to first create a deb that just consists of just /usr/lib64/libc++.a without any headers. Yes, I know per Debian library packaging guide, I should include the file in a *-dev package, But being new to cmake and cpack, I would like to get there incrementally.
So, I first changed the libcxx-3.4/lib/CMakeLists.txt and added an if check (see line 14 and 18)
$ cat CMakeLists.txt
1 if (NOT LIBCXX_INSTALL_SUPPORT_HEADERS)
2 set(LIBCXX_SUPPORT_HEADER_PATTERN PATTERN "support" EXCLUDE)
3 endif()
4
5 file(COPY .
6 DESTINATION "${CMAKE_BINARY_DIR}/include/c++/v1"
7 FILES_MATCHING
8 PATTERN "*"
9 PATTERN "CMakeLists.txt" EXCLUDE
10 PATTERN ".svn" EXCLUDE
11 ${LIBCXX_SUPPORT_HEADER_PATTERN}
12 )
13
14 if (${LIBCXX_ENABLE_SHARED} MATCHES "ON")
15 install(DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1/"
16 DESTINATION include/c++/v1/
17 )
18 endif()
Then, at in the build subdirectory, I issued a
CC=clang CXX=clang++ cmake -j2 -G "Unix Makefiles" -DLIBCXX_CXX_ABI=libcxxabi -DLIBCXX_LIBCXXABI_INCLUDE_PATHS="../libcxxabi/include" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr ../libcxx -DLIBCXX_ENABLE_SHARED=OFF
The created deb still consists of all headers. If I commented out lines 14 to 18, then no headers were included in the package. I am puzzled by this. A variable defined for the parent CMakeLists.txt should be picked up by a child CMakeLists.txt. What did I miss? I would appreciate a hint or two.
I have figured out the answer for my own question. Being new to cmake and cpack, I initially focused on the wrong CMakeLists.txt. The install command for headers in the include/CMakeLists.txt is not the only one. The main CMakeLists.txt file has a marcro in which there is also an install command. That should be disabled too. Specifically:
In the main CMakeLists.txt, one could do:
129 message(STATUS "Inside of setup_abi_libs; LIBCXX_ENABLE_SHARED: ${LIBCXX_ENABLE_SHARED}")
130 if (LIBCXX_ENABLE_SHARED)
131 install(DIRECTORY "${CMAKE_BINARY_DIR}/include/"
132 DESTINATION include/c++/v1
133 FILES_MATCHING
134 PATTERN "*"
135 )
136 endif()
137 endmacro()
Then, in the include/CMakeLists.txt, one could do:
13
14 message(STATUS "Inside of include; LIBCXX_ENABLE_SHARED: ${LIBCXX_ENABLE_SHARED}")
15
16 if (LIBCXX_ENABLE_SHARED)
17 install(DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1/"
18 DESTINATION include/c++/v1/
19 )
20 endif()
This is the end result that I was trying to obtain but failed last night:
$ dpkg-deb -c libcxx_3.4-1_amd64.deb
drwxrwxr-x root/root 0 2014-03-04 08:59 ./usr/
drwxrwxr-x root/root 0 2014-03-04 08:59 ./usr/lib64/
-rw-r--r-- root/root 1928770 2014-03-04 08:58 ./usr/lib64/libc++.a
No more headers. Now I just need to figure out how to change the original CMakeLists.txt files to make a real dev package :)
Please read documenation for if:
MATCHES is for regular expressions, use if (LIBCXX_ENABLE_SHARED) or if (${LIBCXX_ENABLE_SHARED} STREQUAL "ON") instead