Wout12345
Wout12345

Reputation: 191

Compiling library with different flags than main code

My project includes an external library (HPTT) that needs to be compiled and linked with the main part of the code. At the moment, I compile both HPTT and my own source code together with the same compiler flags, using the following CMake file:

cmake_minimum_required(VERSION 2.6)
project(custom_tthresh)

# Default settings
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unknown-pragmas") # -Wno-unknown-pragmas ignores unknown OpenMP pragma's without warnings.
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

file(GLOB SRC "src/*.cpp")
file(GLOB HPTT "src/hptt/*.cpp")
add_executable(experiments ${SRC} ${HPTT})
target_include_directories(experiments PRIVATE /usr/include/eigen3/ src/include/)
add_definitions(-std=c++14)

However, I have two issues with this setup:

How can I set up my CMake file so that it compiles both the library and my own code separately, using different compiler flags, and then links them together? I'd like to stick to some static settings for HPTT (always in release mode, less/no warnings, ...). For full information, these are the current locations of the relevant files:

Update: Thanks for all the advice. I updated my CMake file now:

cmake_minimum_required(VERSION 3.7)
project(custom_tthresh)

# Always compile external dependencies in Release mode
# We use the custom flag CUSTOM_TTHRESH_BUILD_TYPE to determine the build type for our own library and its related executables
set(CUSTOM_TTHRESH_BUILD_TYPE Release FORCE)

# HPTT
set(HPTT_SRCS src/hptt/hptt.cpp src/hptt/plan.cpp src/hptt/transpose.cpp src/hptt/utils.cpp)
add_library(hptt STATIC ${HPTT_SRCS})
target_include_directories(hptt PRIVATE src/include)
target_compile_options(hptt PRIVATE -w)

# Custom TTHRESH
set(CUSTOM_TTHRESH_SRCS
    src/compress.cpp
    src/CompressedIO.cpp
    src/Compressor.cpp
    src/DataBuffer.cpp
    src/decompress.cpp
    src/quantize.cpp
    src/Sizes.cpp
    src/Slice.cpp
    src/st_hosvd.cpp
)
add_library(custom_tthresh STATIC ${CUSTOM_TTHRESH_SRCS})
target_include_directories(custom_tthresh PRIVATE /usr/include/eigen3/)
target_link_libraries(custom_tthresh hptt)
target_compile_options(custom_tthresh PRIVATE -Wall -Wextra -Wno-unknown-pragmas)
if(CUSTOM_TTHRESH_BUILD_TYPE EQUAL Release)
    target_compile_options(custom_tthresh PRIVATE -O3 -DNDEBUG)
else()
    target_compile_options(custom_tthresh PRIVATE -g)
endif()
set_target_properties(custom_tthresh PROPERTIES
    CXX_STANDARD 14
    CXX_STANDARD_REQUIRED ON
)

# Experiments
add_executable(experiments src/experiments.cpp)
target_link_libraries(experiments custom_tthresh)
target_compile_options(experiments PRIVATE -Wall -Wextra -Wno-unknown-pragmas)
if(CUSTOM_TTHRESH_BUILD_TYPE EQUAL Release)
    target_compile_options(custom_tthresh PRIVATE -O3 -DNDEBUG)
else()
    target_compile_options(custom_tthresh PRIVATE -g)
endif()

This seems to address my problems, avoids some of the bad practices pointed out below and actually reflects the structure of the project. I'm still not proud of the use of CUSTOM_TTHRESH_BUILD_TYPE (based on this question), however I couldn't find a better solution.

Upvotes: 3

Views: 923

Answers (2)

KamilCuk
KamilCuk

Reputation: 141940

How can I set up my CMake file so that it compiles both the library and my own code separately, using different compiler flags, and then links them together?

Use target_compile_options and target_link_options separately on targets to specific flags for a specific target.

Your add_definitions(-std=c++14) is doing nothing (because there are no targets after it) and prefer using set_target_properties(target PROPERTIES CXX_STANDARD 14 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO) to portably set C++14.

Upvotes: 0

Waqar
Waqar

Reputation: 9376

Use target_compile_options() to set flags per target:

target_compile_options(experiments PRIVATE "-Wall -Wextra -Wno-unknown-pragmas")

Additionally, don't set flags globally because it sets the flag for everything in the source tree. Don't do this:

set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unknown-pragmas") # don' do this
set(CMAKE_CXX_FLAGS_DEBUG "-g") # especially this
set(CMAKE_CXX_FLAGS_RELEASE "-O3") # and this

Another bad practice is using file globbing. Read Why is cmake file GLOB evil?

file(GLOB SRC "src/*.cpp")
file(GLOB HPTT "src/hptt/*.cpp") #avoid this

And from the cmake docs:

Note: We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate. The CONFIGURE_DEPENDS flag may not work reliably on all generators, or if a new generator is added in the future that cannot support it, projects using it will be stuck. Even if CONFIGURE_DEPENDS works reliably, there is still a cost to perform the check on every rebuild.

This doesn't do what you think it does. It's certainly not setting the C++ standard:

add_definitions(-std=c++14)

To set the C++ standard, use set_target_properties:

set_target_properties(experiments PROPERTIES
    CXX_STANDARD 14           # standard version
    CXX_STANDARD_REQUIRED ON  # required yes
)

You can set the standard globally using set(CMAKE_CXX_STANDARD 14) if you want to, but it may not work with MSVC.

Upvotes: 3

Related Questions