conda-forge / ctng-compiler-activation-feedstock

A conda-smithy repository for ctng-compiler-activation.
BSD 3-Clause "New" or "Revised" License
13 stars 22 forks source link

Don't add -O flags to [C/CXX/F]FLAGS outside of conda-build #80

Open manopapad opened 2 years ago

manopapad commented 2 years ago

Solution to issue cannot be found in the documentation.

Issue

We are using the conda-forge GNU compiler toolchain for building our packages. We would like to transition to also using the conda-forge GNU compilers for development and debugging. Unfortunately, it looks like when we activate an environment containing the GNU compilers, the activation scripts add the -O2 optimization flag to [C/CXX/F]FLAGS, which ends up being picked up by the make toolchain, and thus removes debug info automatically from our builds:

prm-login:~> conda activate test3
prm-login:~> echo $CXXFLAGS
-fvisibility-inlines-hidden -std=c++17 -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /gpfs/fs1/mpapadakis/miniconda3/envs/test3/include

If we wanted to use the compilers, we would have to externally remove this flag from [C/CXX/F]FLAGS after conda activation has completed.

The relevant snippet from the activation script:

if [ "${CONDA_BUILD:-0}" = "1" ]; then
  CXXFLAGS_USED="-fvisibility-inlines-hidden -std=c++17 -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem ${PREFIX}/include -fdebug-prefix-map=${SRC_DIR}=/usr/local/src/conda/${PKG_NAME}-${PKG_VERSION} -fdebug-prefix-map=${PREFIX}=/usr/local/src/conda-prefix"
  DEBUG_CXXFLAGS_USED="-fvisibility-inlines-hidden -std=c++17 -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-all -fno-plt -Og -g -Wall -Wextra -fvar-tracking-assignments -ffunction-sections -pipe -isystem ${PREFIX}/include -fdebug-prefix-map=${SRC_DIR}=/usr/local/src/conda/${PKG_NAME}-${PKG_VERSION} -fdebug-prefix-map=${PREFIX}=/usr/local/src/conda-prefix"
else
  CXXFLAGS_USED="-fvisibility-inlines-hidden -std=c++17 -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem ${CONDA_PREFIX}/include"
  DEBUG_CXXFLAGS_USED="-fvisibility-inlines-hidden -std=c++17 -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-all -fno-plt -Og -g -Wall -Wextra -fvar-tracking-assignments -ffunction-sections -pipe -isystem ${CONDA_PREFIX}/include"
fi

comes from the following lines in the feedstock:

https://github.com/conda-forge/ctng-compiler-activation-feedstock/blob/main/recipe/activate-g%2B%2B.sh#L85-L93

IIUC, the reason for setting these flags outside of conda-build is to improve the chances that a codebase built with these compilers will be ABI-compatible with the pre-built packages in the same conda environment (that were built with similar flags).

I don't believe optimization flags are relevant for this goal. Please correct me if I'm wrong, but I don't think the level of optimization used when compiling a new binary affects whether it is ABI-compatible with a set of existing libraries. Therefore, assuming that the use of the conda-forge compilers outside of conda-build is an expected use case, I think you should not force a level of optimization on users.

I assume a potential fix for this would be to remove -O2 from @CXXFLAGS@ and instead add it explicitly on this line: https://github.com/conda-forge/ctng-compiler-activation-feedstock/blob/main/recipe/activate-g%2B%2B.sh#L88 (and similarly for other flags).

I would note that optimization flags are the most immediately problematic, but the same argument as above could be made for other flags that are set even outside of conda-build, but don't seem relevant to guaranteeing ABI compatibility, e.g. -fmessage-length=0.

Installed packages

# packages in environment at /gpfs/fs1/mpapadakis/miniconda3/envs/test3:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       2_gnu    conda-forge
binutils                  2.36.1               hdd6e379_2    conda-forge
binutils_impl_linux-64    2.36.1               h193b22a_2    conda-forge
binutils_linux-64         2.36                hf3e587d_10    conda-forge
c-compiler                1.4.2                h166bdaf_0    conda-forge
compilers                 1.4.2                ha770c72_0    conda-forge
cxx-compiler              1.4.2                h924138e_0    conda-forge
fortran-compiler          1.4.2                h2a4ca65_0    conda-forge
gcc                       10.3.0              he2824d0_10    conda-forge
gcc_impl_linux-64         10.3.0              hf2f2afa_16    conda-forge
gcc_linux-64              10.3.0              hc39de41_10    conda-forge
gfortran                  10.3.0              h18518b4_10    conda-forge
gfortran_impl_linux-64    10.3.0              h73f4979_16    conda-forge
gfortran_linux-64         10.3.0              hb09a455_10    conda-forge
gxx                       10.3.0              he2824d0_10    conda-forge
gxx_impl_linux-64         10.3.0              hf2f2afa_16    conda-forge
gxx_linux-64              10.3.0              h2593f52_10    conda-forge
kernel-headers_linux-64   2.6.32              he073ed8_15    conda-forge
ld_impl_linux-64          2.36.1               hea4e1c9_2    conda-forge
libgcc-devel_linux-64     10.3.0              he6cfe16_16    conda-forge
libgcc-ng                 12.1.0              h8d9b700_16    conda-forge
libgfortran5              12.1.0              hdcd56e2_16    conda-forge
libgomp                   12.1.0              h8d9b700_16    conda-forge
libsanitizer              10.3.0              h26c7422_16    conda-forge
libstdcxx-devel_linux-64  10.3.0              he6cfe16_16    conda-forge
libstdcxx-ng              12.1.0              ha89aaad_16    conda-forge
sysroot_linux-64          2.12                he073ed8_15    conda-forge

Environment info

active environment : test3
    active env location : /gpfs/fs1/mpapadakis/miniconda3/envs/test3
            shell level : 2
       user config file : /home/mpapadakis/.condarc
 populated config files : /home/mpapadakis/.condarc
          conda version : 4.10.3
    conda-build version : not installed
         python version : 3.9.5.final.0
       virtual packages : __linux=4.15.0=0
                          __glibc=2.27=0
                          __unix=0=0
                          __archspec=1=x86_64
       base environment : /gpfs/fs1/mpapadakis/miniconda3  (writable)
      conda av data dir : /gpfs/fs1/mpapadakis/miniconda3/etc/conda
  conda av metadata url : None
           channel URLs : https://repo.anaconda.com/pkgs/main/linux-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/r/linux-64
                          https://repo.anaconda.com/pkgs/r/noarch
          package cache : /gpfs/fs1/mpapadakis/miniconda3/pkgs
                          /home/mpapadakis/.conda/pkgs
       envs directories : /gpfs/fs1/mpapadakis/miniconda3/envs
                          /home/mpapadakis/.conda/envs
               platform : linux-64
             user-agent : conda/4.10.3 requests/2.25.1 CPython/3.9.5 Linux/4.15.0-167-generic ubuntu/18.04.3 glibc/2.27
                UID:GID : 38092:30
             netrc file : None
           offline mode : False
isuruf commented 2 years ago

Please see https://docs.conda.io/projects/conda-build/en/latest/resources/compiler-tools.html#customizing-the-compilers about customizing compilers.

isuruf commented 2 years ago

IIUC, the reason for setting these flags outside of conda-build is to improve the chances that a codebase built with these compilers will be ABI-compatible with the pre-built packages in the same conda environment (that were built with similar flags).

That's not the only goal. The other goal is to provide compilers outside of conda-build that behave mostly like the compilers in a conda-build setting.

timsnyder commented 2 years ago

@manopapad , you might also find https://conda-forge.org/docs/user/faq.html#faq-compiler-required-options useful. It is possible to use the conda-forge toolchain in an environment without using the activation scripts.

baszalmstra commented 2 years ago

There is also the DEBUG_CXXFLAGS env variable which you can use for debug builds I believe. But that does still contain -Og which also often doesn't given the desired debugging results.

baszalmstra commented 2 years ago

I currently have this in the root of my CMakeLists.txt.

# In a Conda environment the compiler activation scripts by default specify optimization flags. Even in
# debug mode. These flags make proper debugging very hard. To combat this issue, the code below removes the
# optimization flags (specified with `-Ox`) from the C(XX)_FLAGS if the build type is Debug. The compiler
# will then default to -O0, which should allow for proper debugging.
# This assumes that a multi-config generator is not used.
if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_BUILD_TYPE STREQUAL "Debug")
    # Remove the -Ox flag from the compiler flags
    string(REGEX REPLACE "-O[g0-9][ ]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
    string(REGEX REPLACE "-O[g0-9][ ]*" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
endif()
m3vaz commented 1 year ago

The FAQ doesn't seem to discuss running the toolchain without the activation scripts, perhaps the link was meant to go to a specific revision?

Instead of creating an entirely separate compiler package, would it be possible to have an override environment variable for the optimization flags? (e.g. something like CONDA_OVERRIDE_CUDA)

timsnyder commented 1 year ago

The FAQ doesn't seem to discuss running the toolchain without the activation scripts, perhaps the link was meant to go to a specific revision?

You're right. I saw gcc mentioned in https://conda-forge.org/docs/user/faq.html#faq-compiler-required-options and didn't read it carefully enough. If you don't want the activation scripts, install (gcc, gxx and binutils). Those will give you all of the short-named symlinks.

If you don't want to have to specify $CONDA_PREFIX/include and $CONDA_PREFIX/lib via command-line arguments, you might also want the conda-gcc-specs package.

If I get a chance, I'll improve the FAQ entry.

feltech commented 4 months ago

Just to add my +1 to this.

I'd also like to see all the other superfluous/opinionated compiler switches removed. I'd rather manage them myself (e.g. via cmake/conan). Though the forced optimisation flag is the most frustrating.

I take the point that consistency between conda-build/packages and user environments is a goal. Perhaps forking+customising is the only reasonable solution?