How to compile all the libraries as static but one as shared? - cmake

My folder structure is like that:
├── SubLibA
│   ├── CMakeLists.txt
│   ├── include
│   │   └── SubLibA.h
│   └── SubLibA.cpp
├── SubLibB
│   ├── CMakeLists.txt
│   ├── include
│   │   └── structs.h
│   └── SubLibB.cpp
└── SharedLib
├── CMakeLists.txt
├── include
│   └── SharedLib.h
├── SharedLib.cpp
└── SharedLib.h
My global CMakeLists.txt looks like this:
add_subdirectory(SubLibA)
add_subdirectory(SubLibB)
add_subdirectory(SharedLib)
They all compile as static by default.
SharedLib depends on SubLibB that depends on SubLibA.
The dependent libraries SharedLib and SubLibB have:
#SubLibB
target_link_libraries(${PROJECT_NAME}
SubLibA::SubLibA
)
#SharedLib
target_link_libraries(${PROJECT_NAME}
SubLibB::SubLibB
)
Running cmake .. -DBUILD_SHARED_LIBS=ON compiles all the three libs as shared library...
Since they are tightly dependent, I'd like to keep them in the same repository with a unique CMakeLists.txt that compiles them all at once. I want to use the power of Modern CMake with the least hard-coded file and custom files as possible to keep a straightforward maintenance.

Try setting the variable within cmake:
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(SubLibA)
add_subdirectory(SubLibB)
set(BUILD_SHARED_LIBS ON)
add_subdirectory(SharedLib)
set(BUILD_SHARED_LIBS OFF)

If you want SubLibA and SubLibB always be static libraries you can use the STATIC keyword on the add_library command, e.g. add_library(SubLibA STATIC ${SOURCES}) By omitting the keyword for SharedLib you are still free to build it as static or shared lib by setting -DBUILD_SHARED_LIBS=ON on the CMake command line.

Related

Simple way to add a Premake subproject inside a CMake project?

I use CMake for my C++ projects and I like to have my dependencies as Git submodules inside a third-party folder so I can have easy access to the code and the possible CMake targets I can link with.
.
├── CMakeLists.txt
├── src
│   └── main.cpp
└── third-party
└── CMakeSubmodule # OK
└── CMakeLists.txt # OK
My root CMakeLists.txt would typically contain :
add_subdirectory(src)
add_subdirectory(third-party/CMakeSubmodule)
target_link_libraries(myTarget PRIVATE SubmoduleTarget)
Now, I want to add a submodule that only uses premake :
.
├── CMakeLists.txt
├── src
│   └── main.cpp
└── third-party
└── PremakeSubmodule # !
└── premake5.lua # !
How would you do to simply add the submodule as a dependency ?
Do I have to manually convert all premake files to CMakeLists.txt ?
A convenient solution would allow to directly link to a target as follow, so I don't have to manually set the correct include directories and link to the lib files :
target_link_libraries(myTarget PRIVATE PremakeTarget) # Would be great

Does CMake has QMake's .qmake.conf alternative (automatically included file from parent directory) or other means to achieve similar result?

Let's say we have repository structure like this (note the .qmake.conf files):
repo/
├── libraries
│   └── libFoo
│   └── libFoo.pri
├── projects
│   ├── ProjectX
│   │   ├── apps
│   │   │   └── AppX
│   │   │   └── AppX.pro
│   │   ├── libs
│   │   │   └── libX
│   │   │   └── libX.pri
│   │   └── .qmake.conf
│   └── ProjectY
│   ├── apps
│   │   └── AppY
│   │   └── AppY.pro
│   └── .qmake.conf
├── qmake
│   └── common.pri
└── .qmake.conf
QMake supports .qmake.conf files, where you can declare useful variables, and it is automatically included in your .pro file if found in parent directory.
This is how it helps to avoid dealing with ../../.. relative paths, for example:
Root repo/.qmake.conf file has REPO_ROOT=$$PWD declared.
project also has it's own repo/projects/ProjectX/.qmake.conf, which has include(../../.qmake.conf) included and PROJECT_ROOT=$$PWD declared.
project's application .pro file (repo/projects/ProjectX/apps/AppX/AppX.pro) can avoid writing ../../ and include all dependencies from sibling and parent directories like this:
include($${REPO_ROOT}/qmake/common.pri)
include($${REPO_ROOT}/libraries/libFoo/libFoo.pri)
include($${PROJECT_ROOT}/libs/libX/libX.pri)
This is convenient and tidy. You DO have to write ../../ once (and update it if repository tree changes), but only once per new .qmake.conf, and later you can use variables to refer to various useful relative paths in the repository in any number of .pro's you have.
Is three similar technique in CMake? How this kind of variable organization could be achieve with CMake, in most convenient way?
In CMake you can achieve similar result somewhat differently:
(regarding "useful variables" management)
CMake knows about 3 "types of variables":
vars with directory scope; directory scope variables behave in such a way that if you define them in some folder, they will automatically be visible in all subfolders. In brief, if you define some var in root CMakeLists.txt, it will be visible in all project subfolders. Example of defining "directory scope variable":
# outside any function
set(MY_USEFUL_VAR SOME_VALUE)
vars with function scope; function scope variables are variables defined within the function. They are visible in the current function scope and all scopes initiated from it. Example of function scope variable:
function(my_function)
# note that the definition is within the function
set(MY_LOCAL_VAR SOME_VALUE)
# rest of the function body...
endfunction()
cache variables may be considered as "global variables", and those are also stored within CMakeCache.txt file within the root build folder. Cache variables are defined as follows (adding a new string variable):
set (MY_CACHE_VAR "this is some string value" CACHE STRING "explanation of MY_VAR")
Also, as already suggested within the comments, you can place variables definitions into the various "include files" and include them using CMake include statement.
In the end, here is the documentation about set, and include CMake statements.

add_custom_command for copy header files not working

This is my project tree-like format :
├── cmake
│  └── CopyHeaderFiles.cmake
├── CMakeLists.txt
├── common
│   ├── CMakeLists.txt
│   ├── Headers
│   │   ├── CMakeLists.txt
│   │   ├── criticalmessage.h
│   └── Src
│   ├── CMakeLists.txt
│   ├── criticalmessage.cpp
├── includes
│   └── CMakeLists.txt
├── main.cpp
As you see i have a module (common) in my project, my goal is copy all headers file from
PROJECT_SOURCE_DIR/common/Headers to PROJECT_BINARY_DIR/includes with add_custom_command.
this is common/CMakeLists.txt
cmake_minimum_required (VERSION 3.0)
set(MODULE_NAME common)
add_subdirectory(Headers)
add_subdirectory(Src)
include(${PROJECT_SOURCE_DIR}/cmake/CopyHeaderFiles.cmake)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lpthread")
include_directories("${CMAKE_SOURCE_DIR}/common/Headers" )
add_library(${MODULE_NAME} STATIC ${SRC_LIST} ${INCLUDE_LIST})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
And content of cmake/HeaderFiles.cmake:
foreach( headerfile ${INCLUDE_LIST})
add_custom_command(
OUTPUT ${headerfile}
COMMAND ${CMAKE_COMMAND} -E copy
"${PROJECT_SOURCE_DIR}/${MODULE_NAME}/Headers/${headerfile}"
"${PROJECT_BINARY_DIR}/includes"
)
endforeach( headerfile )
But no files exist in include directory and always be empty after build my project.
Where am i wrong?

Cross compile with cmake cannot link test

I try to cross compile a library (Wt) using CMake (2.8.12.2). I get always errors which tell me that it is not able to compile a simple test program.
I do not know how to make cmake to look into the right path for getting object files.
My development and target plattform is Linux.
The error log looks like this
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed.
Compiler: /opt/rhl/0.01/sysroots/x86_64-rhlsdk-linux/usr/bin/arm-reed-linux-gnueabi/arm-reed-linux-gnueabi-gcc
Build flags: ;-O2;-pipe;-g;-feliminate-unused-debug-types;
Id flags:
The output was:
1
/opt/rhl/0.01/sysroots/x86_64-rhlsdk-linux/usr/libexec/arm-reed-linux-gnueabi/gcc/arm-reed-linux-gnueabi/5.3.0/real-ld: cannot find crt1.o: No such file or directory
/opt/rhl/0.01/sysroots/x86_64-rhlsdk-linux/usr/libexec/arm-reed-linux-gnueabi/gcc/arm-reed-linux-gnueabi/5.3.0/real-ld: cannot find crti.o: No such file or directory
...
Here is my tool chain file. I could skip the test (See CMAKE_C_COMPILER_WORKS) but then I get later similar problems:
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
# Compiler and linker
SET(CMAKE_C_COMPILER "/opt/rhl/0.01/sysroots/x86_64-rhlsdk-linux/usr/bin/arm-reed-linux-gnueabi/arm-reed-linux-gnueabi-gcc")
SET(CMAKE_CXX_COMPILER "/opt/rhl/0.01/sysroots/x86_64-rhlsdk-linux/usr/bin/arm-reed-linux-gnueabi/arm-reed-linux-gnueabi-g++")
SET(COMPILE_FLAGS " -march=armv7-a -marm -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a8 --sysroot=/opt/rhl/0.01/sysroots/cortexa8hf-neon-reed-linux-gnueabi")
SET(CMAKE_EXE_LINKER_FLAGS " -O2 -v -o --sysroot=/opt/rhl/0.01/sysroots/cortexa8hf-neon-reed-linux-gnueabi ")
# Paths
SET(CMAKE_PREFIX_PATH /opt/rhl/0.01/sysroots/cortexa8hf-neon-reed-linux-gnueabi/usr/)
SET(CMAKE_SYSROOT /opt/rhl/0.01/sysroots/cortexa8hf-neon-reed-linux-gnueabi/)
SET(CMAKE_FIND_ROOT_PATH /opt/rhl/0.01/sysroots/cortexa8hf-neon-reed-linux-gnueabi/)
SET(CMAKE_COLOR_MAKEFILE ON)
set(SHARED_LIBS OFF)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# skip the compiler tests
# set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")
# set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")
And here is a tree view of my system. I pruned it to show the relevant part.
/opt/rhl/0.01/sysroots
├── cortexa8hf-neon-reed-linux-gnueabi
│   ├── bin
│   ├── lib
│   ├── usr
│   │   ├── bin
│   │   ├── include
│   │   ├── lib
│   │   │   ├── crt1.o -> cmake cannot find this file
│   │   │   ├── crti.o -> cmake cannot find this file
│   │   ├── share
│   │   └── src
│   │   ├── gcc-runtime
│   │   │   └── 5.3.0-r0
└── x86_64-rhlsdk-linux
├── lib
├── sbin
├── usr
│   ├── bin
│   │   │   ├── arm-reed-linux-gcc -> ../arm-reed-linux-gnueabi/arm-reed-linux-gnueabi-gcc
│   │   ├── arm-reed-linux-gnueabi
│   │   │   ├── arm-reed-linux-gnueabi-gcc -> The C compiler
│   ├── include
│   ├── lib
│   ├── libexec

Folder structure in corefx projects

I am trying to understand the folder structure of a corefx project, here System.IO. Here is how the System.IO folder appears in OS X
System.IO BLACKSTAR$ pwd
/Users/BLACKSTAR/dotnet/corefx/src/System.IO
sameer:System.IO BLACKSTAR$ tree
.
├── System.IO.sln
├── ref
│   ├── System.IO.Manual.cs
│   ├── System.IO.cs
│   ├── System.IO.csproj
│   ├── bin
│   │   └── Debug
│   │   └── dotnet
│   │   ├── ref.dll
│   │   └── ref.xml
│   ├── project.json
│   └── project.lock.json
├── src
│   ├── Resources
│   │   └── Strings.resx
│   ├── System
│   │   └── IO
│   │   └── InvalidDataException.cs
│   ├── System.IO.csproj
│   ├── project.json
│   └── project.lock.json
Here is what I am trying to figure out
What is there in ref folder?
What is there in src folder?
What is the connection between ref and src?
Ref is targeted to dotnet but Src is targeted to dnxcore50 framework. What does this imply?
I was able to build the project in ref folder but i couldn't build the project in src using dnu build though dnu restore ran successfully. What am I doing wrong?
sameer:System.IO BLACKSTAR$ dnvm list
Active Version Runtime Architecture OperatingSystem Alias
------ ------- ------- ------------ --------------- -----
1.0.0-beta7 coreclr x64 darwin
* 1.0.0-beta7 mono linux/osx default
sameer:System.IO BLACKSTAR$
What you See here is a NuGet package for a namespace which is in reality part of the CLR. Some types are needed very early... Like file io and elementary data types so they are part of the CLR distribution. You can find these in the core CLR github project.
So ...
Ref are empty implementations for design time. They are there to define the types.
SRC is the dnxcore5 based implementation... Essentially being empty.
Ref vs SRC.... Ref is used for lookup of the types ... Binding to the implementation (either in coreclr or mscorlib) is done by some PCL type forwards.
SRC is the pseudo implementation for coreclr. Maybe just the missing types. Ref targets dotnet since all modern SDK have type forwards for System.IO.
I have no idea how they are build.
Sorry for the missing details. It is not very well documented by MS.