From 0e9f4bc00c6b26f254e74063e4026ac33b786513 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 18 May 2013 12:12:18 +0200 Subject: [PATCH] Introduce target property _VISIBILITY_PRESET This is initialized by CMAKE__VISIBILITY_PRESET. The target property is used as the operand to the -fvisibility= compile option with GNU compilers and clang. --- Modules/Compiler/Clang.cmake | 1 + Modules/Compiler/GNU.cmake | 3 ++ Modules/Compiler/Intel-C.cmake | 4 ++ Modules/Compiler/Intel-CXX.cmake | 4 ++ Source/cmGlobalXCodeGenerator.cxx | 3 ++ Source/cmLocalGenerator.cxx | 48 +++++++++++++++++++ Source/cmLocalGenerator.h | 2 + Source/cmMakefileTargetGenerator.cxx | 3 ++ Source/cmNinjaTargetGenerator.cxx | 3 ++ Source/cmTarget.cxx | 21 ++++++++ .../GenerateExportHeader/CMakeLists.txt | 2 + .../visibility_preset/CMakeLists.txt | 13 +++++ .../visibility_preset/main.cpp | 9 ++++ .../visibility_preset/visibility_preset.cpp | 7 +++ .../visibility_preset/visibility_preset.h | 13 +++++ Tests/RunCMake/CMakeLists.txt | 16 +++++++ .../RunCMake/VisibilityPreset/CMakeLists.txt | 8 ++++ .../VisibilityPreset/PropertyTypo-result.txt | 1 + .../VisibilityPreset/PropertyTypo-stderr.txt | 1 + .../VisibilityPreset/PropertyTypo.cmake | 3 ++ .../VisibilityPreset/RunCMakeTest.cmake | 3 ++ Tests/RunCMake/VisibilityPreset/lib.cpp | 5 ++ 22 files changed, 173 insertions(+) create mode 100644 Tests/Module/GenerateExportHeader/visibility_preset/CMakeLists.txt create mode 100644 Tests/Module/GenerateExportHeader/visibility_preset/main.cpp create mode 100644 Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.cpp create mode 100644 Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.h create mode 100644 Tests/RunCMake/VisibilityPreset/CMakeLists.txt create mode 100644 Tests/RunCMake/VisibilityPreset/PropertyTypo-result.txt create mode 100644 Tests/RunCMake/VisibilityPreset/PropertyTypo-stderr.txt create mode 100644 Tests/RunCMake/VisibilityPreset/PropertyTypo.cmake create mode 100644 Tests/RunCMake/VisibilityPreset/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/VisibilityPreset/lib.cpp diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index c6cd8f8f5..ec4562a3d 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -24,4 +24,5 @@ macro(__compiler_clang lang) __compiler_gnu(${lang}) set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") endmacro() diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index faad41672..504704dad 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -25,6 +25,9 @@ macro(__compiler_gnu lang) if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") endif() + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.2) + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") + endif() set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake index e23317c14..5b43db9f4 100644 --- a/Modules/Compiler/Intel-C.cmake +++ b/Modules/Compiler/Intel-C.cmake @@ -6,5 +6,9 @@ set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -DNDEBUG") +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0) + set(CMAKE_C_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") +endif() + set(CMAKE_C_CREATE_PREPROCESSED_SOURCE " -E > ") set(CMAKE_C_CREATE_ASSEMBLY_SOURCE " -S -o ") diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake index ae6021a68..35bb3ec04 100644 --- a/Modules/Compiler/Intel-CXX.cmake +++ b/Modules/Compiler/Intel-CXX.cmake @@ -6,5 +6,9 @@ set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -DNDEBUG") +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) + set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") +endif() + set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE " -E > ") set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE " -S -o ") diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 870bfa1fa..13a14e1c8 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1684,6 +1684,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Add shared-library flags if needed. this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang, configName); + + this->CurrentLocalGenerator->AddVisibilityPresetFlags(flags, &target, + lang); } else if(binary) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index d346f1663..71dd3e9ae 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1992,6 +1992,54 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, } } +//---------------------------------------------------------------------------- +void cmLocalGenerator +::AddVisibilityPresetFlags(std::string &flags, cmTarget* target, + const char *lang) +{ + int targetType = target->GetType(); + bool suitableTarget = ((targetType == cmTarget::SHARED_LIBRARY) + || (targetType == cmTarget::MODULE_LIBRARY) + || (target->IsExecutableWithExports())); + + if (!suitableTarget) + { + return; + } + + if (!lang) + { + return; + } + std::string l(lang); + std::string compileOption = "CMAKE_" + l + "_COMPILE_OPTIONS_VISIBILITY"; + const char *opt = this->Makefile->GetDefinition(compileOption.c_str()); + if (!opt) + { + return; + } + std::string flagDefine = l + "_VISIBILITY_PRESET"; + + const char *prop = target->GetProperty(flagDefine.c_str()); + if (!prop) + { + return; + } + if (strcmp(prop, "hidden") != 0 + && strcmp(prop, "default") != 0 + && strcmp(prop, "protected") != 0 + && strcmp(prop, "internal") != 0 ) + { + cmOStringStream e; + e << "Target " << target->GetName() << " uses unsupported value \"" + << prop << "\" for " << flagDefine << "."; + cmSystemTools::Error(e.str().c_str()); + return; + } + std::string option = std::string(opt) + prop; + this->AppendFlags(flags, option.c_str()); +} + //---------------------------------------------------------------------------- void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, std::string const& lang, diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index a1c34f076..84fd58c05 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -143,6 +143,8 @@ public: const char* config); void AddCMP0018Flags(std::string &flags, cmTarget* target, std::string const& lang, const char *config); + void AddVisibilityPresetFlags(std::string &flags, cmTarget* target, + const char *lang); void AddConfigVariableFlags(std::string& flags, const char* var, const char* config); ///! Append flags to a string. diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4220ae148..a7be669f8 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -271,6 +271,9 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang, this->ConfigName); + this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, + lang); + // Add include directory flags. this->AddIncludeFlags(flags, lang); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 850e5ea11..778f86a79 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -150,6 +150,9 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, language.c_str(), this->GetConfigName()); + this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, + language.c_str()); + // Add include directory flags. { std::vector includes; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index eb746b109..c34c3ab85 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -923,6 +923,24 @@ void cmTarget::DefineProperties(cmake *cm) "A target property that can be set to override the prefix " "(such as \"lib\") on a library name."); + cm->DefineProperty + ("C_VISIBILITY_PRESET", cmProperty::TARGET, + "Value for symbol visibility compile flags", + "The C_VISIBILITY_PRESET property determines the value passed used in " + "a visibility related compile option, such as -fvisibility=. This " + "property only has an affect for libraries and executables with " + "exports. This property is initialized by the value of the variable " + "CMAKE_C_VISIBILITY_PRESET if it is set when a target is created."); + + cm->DefineProperty + ("CXX_VISIBILITY_PRESET", cmProperty::TARGET, + "Value for symbol visibility compile flags", + "The CXX_VISIBILITY_PRESET property determines the value passed used in " + "a visibility related compile option, such as -fvisibility=. This " + "property only has an affect for libraries and executables with " + "exports. This property is initialized by the value of the variable " + "CMAKE_CXX_VISIBILITY_PRESET if it is set when a target is created."); + cm->DefineProperty ("POSITION_INDEPENDENT_CODE", cmProperty::TARGET, "Whether to create a position-independent target", @@ -1560,6 +1578,9 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->InsertInclude(*it); } + this->SetPropertyDefault("C_VISIBILITY_PRESET", 0); + this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0); + if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) { diff --git a/Tests/Module/GenerateExportHeader/CMakeLists.txt b/Tests/Module/GenerateExportHeader/CMakeLists.txt index 4a5b1cb5a..359a1e3f5 100644 --- a/Tests/Module/GenerateExportHeader/CMakeLists.txt +++ b/Tests/Module/GenerateExportHeader/CMakeLists.txt @@ -141,6 +141,8 @@ endmacro() include(GenerateExportHeader) +add_subdirectory(visibility_preset) + add_compiler_export_flags() set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/CMakeLists.txt b/Tests/Module/GenerateExportHeader/visibility_preset/CMakeLists.txt new file mode 100644 index 000000000..ffa938057 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/CMakeLists.txt @@ -0,0 +1,13 @@ + +set(CMAKE_CXX_VISIBILITY_PRESET hidden) + +if (CMAKE_CXX_FLAGS MATCHES "-fvisibility=hidden") + message(SEND_ERROR "Do not use add_compiler_export_flags before adding this directory") +endif() + +add_library(visibility_preset SHARED visibility_preset.cpp) +generate_export_header(visibility_preset) + +add_executable(visibility_preset_exe main.cpp) + +target_link_libraries(visibility_preset_exe visibility_preset) diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/main.cpp b/Tests/Module/GenerateExportHeader/visibility_preset/main.cpp new file mode 100644 index 000000000..89c397784 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/main.cpp @@ -0,0 +1,9 @@ + +#include "visibility_preset.h" + +int main() +{ + VisibilityPreset vp; + vp.someMethod(); + return 0; +} diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.cpp b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.cpp new file mode 100644 index 000000000..c97dec6e2 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.cpp @@ -0,0 +1,7 @@ + +#include "visibility_preset.h" + +void VisibilityPreset::someMethod() +{ + +} diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.h b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.h new file mode 100644 index 000000000..8becbe189 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.h @@ -0,0 +1,13 @@ + +#ifndef VISIBILITY_PRESET_H +#define VISIBILITY_PRESET_H + +#include "visibility_preset_export.h" + +class VISIBILITY_PRESET_EXPORT VisibilityPreset +{ +public: + void someMethod(); +}; + +#endif diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index f6761077d..30be228a6 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -65,6 +65,22 @@ add_RunCMake_test(Languages) add_RunCMake_test(ObjectLibrary) if(NOT WIN32) add_RunCMake_test(PositionIndependentCode) + set(SKIP_VISIBILITY 0) + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 4.2) + set(SKIP_VISIBILITY 1) + endif() + + if (CMAKE_CXX_COMPILER_ID MATCHES Watcom + OR CMAKE_SYSTEM_NAME MATCHES IRIX64 + OR CMAKE_CXX_COMPILER_ID MATCHES HP + OR CMAKE_CXX_COMPILER_ID MATCHES XL + OR CMAKE_CXX_COMPILER_ID MATCHES SunPro) + set(SKIP_VISIBILITY 1) + endif() + + if (NOT SKIP_VISIBILITY) + add_RunCMake_test(VisibilityPreset) + endif() endif() add_RunCMake_test(CompatibleInterface) diff --git a/Tests/RunCMake/VisibilityPreset/CMakeLists.txt b/Tests/RunCMake/VisibilityPreset/CMakeLists.txt new file mode 100644 index 000000000..22577da4a --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/CMakeLists.txt @@ -0,0 +1,8 @@ + +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} CXX) + +# MSVC creates extra targets which pollute the stderr unless we set this. +set(CMAKE_SUPPRESS_REGENERATION TRUE) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/VisibilityPreset/PropertyTypo-result.txt b/Tests/RunCMake/VisibilityPreset/PropertyTypo-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/PropertyTypo-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/VisibilityPreset/PropertyTypo-stderr.txt b/Tests/RunCMake/VisibilityPreset/PropertyTypo-stderr.txt new file mode 100644 index 000000000..ca8c33f36 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/PropertyTypo-stderr.txt @@ -0,0 +1 @@ +CMake Error: Target visibility_preset uses unsupported value \"hiden\" for CXX_VISIBILITY_PRESET diff --git a/Tests/RunCMake/VisibilityPreset/PropertyTypo.cmake b/Tests/RunCMake/VisibilityPreset/PropertyTypo.cmake new file mode 100644 index 000000000..03c0ed9a2 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/PropertyTypo.cmake @@ -0,0 +1,3 @@ + +add_library(visibility_preset SHARED lib.cpp) +set_property(TARGET visibility_preset PROPERTY CXX_VISIBILITY_PRESET hiden) diff --git a/Tests/RunCMake/VisibilityPreset/RunCMakeTest.cmake b/Tests/RunCMake/VisibilityPreset/RunCMakeTest.cmake new file mode 100644 index 000000000..2d7883208 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(PropertyTypo) diff --git a/Tests/RunCMake/VisibilityPreset/lib.cpp b/Tests/RunCMake/VisibilityPreset/lib.cpp new file mode 100644 index 000000000..06b3472f2 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/lib.cpp @@ -0,0 +1,5 @@ + +int foo(void) +{ + return 42; +}