diff --git a/CMakeLists.txt b/CMakeLists.txt index ac3b978..dd50236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -342,9 +342,21 @@ option (LLVM_ENABLE_SPHINX "Use Sphinx to generate llvm documentation." OFF) option (LLVM_BUILD_EXTERNAL_COMPILER_RT "Build compiler-rt as an external project." OFF) -option(LLVM_BUILD_LLVM_DYLIB "Build libllvm dynamic library" OFF) -option(LLVM_DYLIB_EXPORT_ALL "Export all symbols from libLLVM.dylib (default is C API only" OFF) -option(LLVM_DISABLE_LLVM_DYLIB_ATEXIT "Disable llvm-shlib's atexit destructors." ON) +# You can configure which libraries from LLVM you want to include in the +# shared library by setting LLVM_DYLIB_COMPONENTS to a semi-colon delimited +# list of LLVM components. All component names handled by llvm-config are valid. +if(NOT DEFINED LLVM_DYLIB_COMPONENTS) + set(LLVM_DYLIB_COMPONENTS "all" CACHE STRING + "Semicolon-separated list of components to include in libLLVM, or \"all\".") +endif() +option(LLVM_LINK_LLVM_DYLIB "Link tools against the libllvm dynamic library" OFF) +option(LLVM_BUILD_LLVM_DYLIB "Build libllvm dynamic library" ${LLVM_LINK_LLVM_DYLIB}) +option(LLVM_DYLIB_EXPORT_ALL "Export all symbols from libLLVM.dylib (default is C API only" ${LLVM_LINK_LLVM_DYLIB}) +set(LLVM_DISABLE_LLVM_DYLIB_ATEXIT_DEFAULT ON) +if (LLVM_LINK_LLVM_DYLIB) + set(LLVM_DISABLE_LLVM_DYLIB_ATEXIT_DEFAULT OFF) +endif() +option(LLVM_DISABLE_LLVM_DYLIB_ATEXIT "Disable llvm-shlib's atexit destructors." ${LLVM_DISABLE_LLVM_DYLIB_ATEXIT_DEFAULT}) if(LLVM_DISABLE_LLVM_DYLIB_ATEXIT) set(DISABLE_LLVM_DYLIB_ATEXIT 1) endif() diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake index 45f6746..6b6e6e0 100644 --- a/cmake/modules/AddLLVM.cmake +++ b/cmake/modules/AddLLVM.cmake @@ -41,7 +41,7 @@ function(llvm_update_compile_flags name) # Assume that; # - LLVM_COMPILE_FLAGS is list. # - PROPERTY COMPILE_FLAGS is string. - string(REPLACE ";" " " target_compile_flags "${LLVM_COMPILE_FLAGS}") + string(REPLACE ";" " " target_compile_flags " ${LLVM_COMPILE_FLAGS}") if(update_src_props) foreach(fn ${sources}) @@ -303,6 +303,9 @@ endfunction(set_windows_version_resource_properties) # MODULE # Target ${name} might not be created on unsupported platforms. # Check with "if(TARGET ${name})". +# DISABLE_LLVM_LINK_LLVM_DYLIB +# Do not link this library to libLLVM, even if +# LLVM_LINK_LLVM_DYLIB is enabled. # OUTPUT_NAME name # Corresponds to OUTPUT_NAME in target properties. # DEPENDS targets... @@ -316,7 +319,7 @@ endfunction(set_windows_version_resource_properties) # ) function(llvm_add_library name) cmake_parse_arguments(ARG - "MODULE;SHARED;STATIC" + "MODULE;SHARED;STATIC;DISABLE_LLVM_LINK_LLVM_DYLIB" "OUTPUT_NAME" "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS;OBJLIBS" ${ARGN}) @@ -444,10 +447,14 @@ function(llvm_add_library name) # property has been set to an empty value. get_property(lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${name}) - llvm_map_components_to_libnames(llvm_libs - ${ARG_LINK_COMPONENTS} - ${LLVM_LINK_COMPONENTS} - ) + if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_STATIC AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB) + set(llvm_libs LLVM) + else() + llvm_map_components_to_libnames(llvm_libs + ${ARG_LINK_COMPONENTS} + ${LLVM_LINK_COMPONENTS} + ) + endif() if(CMAKE_VERSION VERSION_LESS 2.8.12) # Link libs w/o keywords, assuming PUBLIC. @@ -562,7 +569,22 @@ endmacro(add_llvm_loadable_module name) macro(add_llvm_executable name) - llvm_process_sources( ALL_FILES ${ARGN} ) + cmake_parse_arguments(ARG "DISABLE_LLVM_LINK_LLVM_DYLIB" "" "" ${ARGN}) + llvm_process_sources( ALL_FILES ${ARG_UNPARSED_ARGUMENTS} ) + + # Generate objlib + if(LLVM_ENABLE_OBJLIB) + # Generate an obj library for both targets. + set(obj_name "obj.${name}") + add_library(${obj_name} OBJECT EXCLUDE_FROM_ALL + ${ALL_FILES} + ) + llvm_update_compile_flags(${obj_name}) + set(ALL_FILES "$") + + set_target_properties(${obj_name} PROPERTIES FOLDER "Object Libraries") + endif() + add_windows_version_resource_file(ALL_FILES ${ALL_FILES}) if( EXCLUDE_FROM_ALL ) @@ -588,9 +610,13 @@ macro(add_llvm_executable name) add_llvm_symbol_exports( ${name} ${LLVM_EXPORTED_SYMBOL_FILE} ) endif(LLVM_EXPORTED_SYMBOL_FILE) + if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB) + set(USE_SHARED USE_SHARED) + endif() + set(EXCLUDE_FROM_ALL OFF) set_output_directory(${name} ${LLVM_RUNTIME_OUTPUT_INTDIR} ${LLVM_LIBRARY_OUTPUT_INTDIR}) - llvm_config( ${name} ${LLVM_LINK_COMPONENTS} ) + llvm_config( ${name} ${USE_SHARED} ${LLVM_LINK_COMPONENTS} ) if( LLVM_COMMON_DEPENDS ) add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) endif( LLVM_COMMON_DEPENDS ) @@ -651,7 +677,7 @@ endmacro(add_llvm_example name) macro(add_llvm_utility name) - add_llvm_executable(${name} ${ARGN}) + add_llvm_executable(${name} DISABLE_LLVM_LINK_LLVM_DYLIB ${ARGN}) set_target_properties(${name} PROPERTIES FOLDER "Utils") if( LLVM_INSTALL_UTILS ) install (TARGETS ${name} @@ -785,8 +811,13 @@ function(llvm_add_go_executable binary pkgpath) set(cppflags "${cppflags} -I${d}") endforeach(d) set(ldflags "${CMAKE_EXE_LINKER_FLAGS}") + if (LLVM_LINK_LLVM_DYLIB) + set(linkmode "dylib") + else() + set(linkmode "component-libs") + endif() add_custom_command(OUTPUT ${binpath} - COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}" + COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "go=${GO_EXECUTABLE}" "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}" "linkmode=${linkmode}" ${ARG_GOFLAGS} build -o ${binpath} ${pkgpath} DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX} ${llvmlibs} ${ARG_DEPENDS} diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index 22ac714..aa68b40 100644 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -31,7 +31,23 @@ endfunction(is_llvm_target_library) macro(llvm_config executable) - explicit_llvm_config(${executable} ${ARGN}) + cmake_parse_arguments(ARG "USE_SHARED" "" "" ${ARGN}) + set(link_components ${ARG_UNPARSED_ARGUMENTS}) + + if(USE_SHARED) + # If USE_SHARED is specified, then we link against libLLVM, + # but also against the component libraries below. This is + # done in case libLLVM does not contain all of the components + # the target requires. + # + # TODO strip LLVM_DYLIB_COMPONENTS out of link_components. + # To do this, we need special handling for "all", since that + # may imply linking to libraries that are not included in + # libLLVM. + target_link_libraries(${executable} LLVM) + endif() + + explicit_llvm_config(${executable} ${link_components}) endmacro(llvm_config) diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake index 85d720e..fcb445a 100644 --- a/cmake/modules/TableGen.cmake +++ b/cmake/modules/TableGen.cmake @@ -73,6 +73,10 @@ endfunction() macro(add_tablegen target project) set(${target}_OLD_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS}) set(LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} TableGen) + + # FIXME: It leaks to user, callee of add_tablegen. + set(LLVM_ENABLE_OBJLIB ON) + add_llvm_utility(${target} ${ARGN}) set(LLVM_LINK_COMPONENTS ${${target}_OLD_LLVM_LINK_COMPONENTS}) diff --git a/tools/llvm-go/llvm-go.go b/tools/llvm-go/llvm-go.go index c5c3fd2..ed79ca6 100644 --- a/tools/llvm-go/llvm-go.go +++ b/tools/llvm-go/llvm-go.go @@ -24,6 +24,11 @@ import ( "strings" ) +const ( + linkmodeComponentLibs = "component-libs" + linkmodeDylib = "dylib" +) + type pkg struct { llvmpath, pkgpath string } @@ -66,11 +71,12 @@ var components = []string{ func llvmConfig(args ...string) string { configpath := os.Getenv("LLVM_CONFIG") if configpath == "" { - // strip llvm-go, add llvm-config - configpath = os.Args[0][:len(os.Args[0])-7] + "llvm-config" + bin, _ := filepath.Split(os.Args[0]) + configpath = filepath.Join(bin, "llvm-config") } cmd := exec.Command(configpath, args...) + cmd.Stderr = os.Stderr out, err := cmd.Output() if err != nil { panic(err.Error()) @@ -78,11 +84,21 @@ func llvmConfig(args ...string) string { outstr := string(out) outstr = strings.TrimSuffix(outstr, "\n") - return strings.Replace(outstr, "\n", " ", -1) + outstr = strings.Replace(outstr, "\n", " ", -1) + return outstr } -func llvmFlags() compilerFlags { - ldflags := llvmConfig(append([]string{"--ldflags", "--libs", "--system-libs"}, components...)...) +func llvmFlags(linkmode string) compilerFlags { + ldflags := llvmConfig("--ldflags") + switch linkmode { + case linkmodeComponentLibs: + ldflags += " " + llvmConfig(append([]string{"--libs"}, components...)...) + case linkmodeDylib: + ldflags += " -lLLVM" + default: + panic("invalid linkmode: " + linkmode) + } + ldflags += " " + llvmConfig("--system-libs") if runtime.GOOS != "darwin" { // OS X doesn't like -rpath with cgo. See: // https://code.google.com/p/go/issues/detail?id=7293 @@ -117,8 +133,8 @@ func printComponents() { fmt.Println(strings.Join(components, " ")) } -func printConfig() { - flags := llvmFlags() +func printConfig(linkmode string) { + flags := llvmFlags(linkmode) fmt.Printf(`// +build !byollvm @@ -137,7 +153,7 @@ type (run_build_sh int) `, flags.cpp, flags.cxx, flags.ld) } -func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags string) { +func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags, linkmode string) { args = addTag(args, "byollvm") srcdir := llvmConfig("--src-root") @@ -166,7 +182,7 @@ func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, l newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...) newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator)) - flags := llvmFlags() + flags := llvmFlags(linkmode) newenv := []string{ "CC=" + cc, @@ -178,7 +194,7 @@ func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, l "PATH=" + newpath, } if llgo != "" { - newenv = append(newenv, "GCCGO=" + llgo) + newenv = append(newenv, "GCCGO="+llgo) } for _, v := range os.Environ() { @@ -234,45 +250,44 @@ func main() { ldflags := os.Getenv("CGO_LDFLAGS") gocmd := "go" llgo := "" + linkmode := linkmodeComponentLibs + + flags := []struct { + name string + dest *string + }{ + {"cc", &cc}, + {"cxx", &cxx}, + {"go", &gocmd}, + {"llgo", &llgo}, + {"cppflags", &cppflags}, + {"ldflags", &ldflags}, + {"linkmode", &linkmode}, + } args := os.Args[1:] - DONE: for { - switch { - case len(args) == 0: +LOOP: + for { + if len(args) == 0 { usage() - case strings.HasPrefix(args[0], "cc="): - cc = args[0][3:] - args = args[1:] - case strings.HasPrefix(args[0], "cxx="): - cxx = args[0][4:] - args = args[1:] - case strings.HasPrefix(args[0], "go="): - gocmd = args[0][3:] - args = args[1:] - case strings.HasPrefix(args[0], "llgo="): - llgo = args[0][5:] - args = args[1:] - case strings.HasPrefix(args[0], "cppflags="): - cppflags = args[0][9:] - args = args[1:] - case strings.HasPrefix(args[0], "cxxflags="): - cxxflags = args[0][9:] - args = args[1:] - case strings.HasPrefix(args[0], "ldflags="): - ldflags = args[0][8:] - args = args[1:] - default: - break DONE } + for _, flag := range flags { + if strings.HasPrefix(args[0], flag.name+"=") { + *flag.dest = args[0][len(flag.name)+1:] + args = args[1:] + continue LOOP + } + } + break } switch args[0] { case "build", "get", "install", "run", "test": - runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags) + runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags, linkmode) case "print-components": printComponents() case "print-config": - printConfig() + printConfig(linkmode) default: usage() } diff --git a/tools/llvm-shlib/CMakeLists.txt b/tools/llvm-shlib/CMakeLists.txt index 54d71d3..d9bd15f 100644 --- a/tools/llvm-shlib/CMakeLists.txt +++ b/tools/llvm-shlib/CMakeLists.txt @@ -2,42 +2,6 @@ # library is enabled by setting LLVM_BUILD_LLVM_DYLIB=yes on the CMake # commandline. By default the shared library only exports the LLVM C API. - -# You can configure which libraries from LLVM you want to include in the shared -# library by setting LLVM_DYLIB_COMPONENTS to a semi-colon delimited list of -# LLVM components. All compoenent names handled by llvm-config are valid. - -if(NOT DEFINED LLVM_DYLIB_COMPONENTS) - set(LLVM_DYLIB_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} - Analysis - BitReader - BitWriter - CodeGen - Core - DebugInfoDWARF - DebugInfoPDB - ExecutionEngine - IPA - IPO - IRReader - InstCombine - Instrumentation - Interpreter - Linker - MCDisassembler - MCJIT - ObjCARCOpts - Object - ScalarOpts - Support - Target - TransformUtils - Vectorize - native - ) -endif() - add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) set(SOURCES @@ -46,6 +10,29 @@ set(SOURCES llvm_map_components_to_libnames(LIB_NAMES ${LLVM_DYLIB_COMPONENTS}) +if(LLVM_LINK_LLVM_DYLIB) + if(NOT LLVM_DYLIB_EXPORT_ALL) + message(FATAL_ERROR "LLVM_DYLIB_EXPORT_ALL must be ON when LLVM_LINK_LLVM_DYLIB is ON") + endif() + + # libLLVM.so should not have any dependencies on any other LLVM + # shared libraries. When using the "all" pseudo-component, + # LLVM_AVAILABLE_LIBS is added to the dependencies, which may + # contain shared libraries (e.g. libLTO). + # + # Also exclude libLLVMTableGen for the following reasons: + # - it is only used by internal *-tblgen utilities; + # - it pollutes the global options space. + foreach(lib ${LIB_NAMES}) + get_target_property(t ${lib} TYPE) + if("${lib}" STREQUAL "LLVMTableGen") + elseif("x${t}" STREQUAL "xSTATIC_LIBRARY") + list(APPEND FILTERED_LIB_NAMES ${lib}) + endif() + endforeach() + set(LIB_NAMES ${FILTERED_LIB_NAMES}) +endif() + if(NOT DEFINED LLVM_DYLIB_EXPORTED_SYMBOL_FILE) if( WIN32 AND NOT CYGWIN ) @@ -95,7 +82,7 @@ else() add_custom_target(libLLVMExports DEPENDS ${LLVM_EXPORTED_SYMBOL_FILE}) endif() -add_llvm_library(LLVM SHARED ${SOURCES}) +add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB ${SOURCES}) list(REMOVE_DUPLICATES LIB_NAMES) if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") # FIXME: It should be "GNU ld for elf"