[llvm] r246527 - Enable linking tools, shared libraries against libLLVM

Andrew Wilkins via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 31 20:14:31 PDT 2015


Author: axw
Date: Mon Aug 31 22:14:31 2015
New Revision: 246527

URL: http://llvm.org/viewvc/llvm-project?rev=246527&view=rev
Log:
Enable linking tools, shared libraries against libLLVM

Summary:
Three closely related changes, to have a mode in which we link all
executables and shared libraries against libLLVM. 

1. Add a new LLVM_LINK_LLVM_DYLIB cmake option, which, when ON, will link
   executables and shared libraries against libLLVM. For this to work, it
   is necessary to also set LLVM_BUILD_LLVM_DYLIB and LLVM_DYLIB_EXPORT_ALL.

   It is not strictly necessary to set LLVM_DISABLE_LLVM_DYLIB_ATEXIT, but
   we also default to OFF in this mode, or tools tend to misbehave (e.g.
   stdout may not flush on exit when output is buffered.)

   llvm-config and Tablegen do not use libLLVM, as they are dependencies of
   libLLVM.

2. Modify llvm-go to take a new flag, "linkmode=component-libs|dylib".
   Depending on which one is passed (default is component-libs), we link
   with the individual libraries or libLLVM respectively. We pass in dylib
   when LLVM_LINK_LLVM_DYLIB is ON.

3. Fix LLVM_DYLIB_EXPORT_ALL on Linux, and expand the symbols exported to
   actually export all. Don't strip leading underscore from symbols on Linux,
   and make sure we get all exported symbols and weak-with-default symbols
   ("W" in nm output). Without these changes, passes won't load because
   the "Annotate..." symbols defined in lib/Support/Valigrind.cpp are not
   found.

Testing:
 - Ran default build ("ninja") with LLVM, clang, compiler-rt, llgo, lldb.
 - Ran "check", "check-clang", "check-tsan", "check-libgo" targets. I've
   never had much success with LLDB tests, and llgoi is currently broken
   so check-llgo fails for an unrelated reason.
 - Ran "lldb" to ensure it loads.

Reviewers: chandlerc, beanz, pcc, rnk

Subscribers: rnk, chapuni, sylvestre.ledru, llvm-commits

Differential Revision: http://reviews.llvm.org/D12488

Modified:
    llvm/trunk/CMakeLists.txt
    llvm/trunk/cmake/modules/AddLLVM.cmake
    llvm/trunk/cmake/modules/TableGen.cmake
    llvm/trunk/tools/llvm-go/llvm-go.go
    llvm/trunk/tools/llvm-shlib/CMakeLists.txt

Modified: llvm/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/CMakeLists.txt?rev=246527&r1=246526&r2=246527&view=diff
==============================================================================
--- llvm/trunk/CMakeLists.txt (original)
+++ llvm/trunk/CMakeLists.txt Mon Aug 31 22:14:31 2015
@@ -347,9 +347,14 @@ option (LLVM_ENABLE_SPHINX "Use Sphinx t
 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)
+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()

Modified: llvm/trunk/cmake/modules/AddLLVM.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/AddLLVM.cmake?rev=246527&r1=246526&r2=246527&view=diff
==============================================================================
--- llvm/trunk/cmake/modules/AddLLVM.cmake (original)
+++ llvm/trunk/cmake/modules/AddLLVM.cmake Mon Aug 31 22:14:31 2015
@@ -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
 #   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
 #   )
 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,8 @@ 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)
@@ -604,7 +612,11 @@ macro(add_llvm_executable name)
 
   set(EXCLUDE_FROM_ALL OFF)
   set_output_directory(${name} ${LLVM_RUNTIME_OUTPUT_INTDIR} ${LLVM_LIBRARY_OUTPUT_INTDIR})
-  llvm_config( ${name} ${LLVM_LINK_COMPONENTS} )
+  if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB)
+    target_link_libraries(${name} LLVM)
+  else()
+    llvm_config( ${name} ${LLVM_LINK_COMPONENTS} )
+  endif()
   if( LLVM_COMMON_DEPENDS )
     add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} )
   endif( LLVM_COMMON_DEPENDS )
@@ -836,8 +848,13 @@ function(llvm_add_go_executable binary p
       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 "go=${GO_EXECUTABLE}" "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}

Modified: llvm/trunk/cmake/modules/TableGen.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/TableGen.cmake?rev=246527&r1=246526&r2=246527&view=diff
==============================================================================
--- llvm/trunk/cmake/modules/TableGen.cmake (original)
+++ llvm/trunk/cmake/modules/TableGen.cmake Mon Aug 31 22:14:31 2015
@@ -77,7 +77,13 @@ macro(add_tablegen target project)
   # FIXME: It leaks to user, callee of add_tablegen.
   set(LLVM_ENABLE_OBJLIB ON)
 
-  add_llvm_utility(${target} ${ARGN})
+  add_llvm_utility(
+    ${target} ${ARGN}
+    # libLLVM does not include the TableGen
+    # components, so we cannot link any tblgen
+    # utilities against it.
+    DISABLE_LLVM_LINK_LLVM_DYLIB)
+
   set(LLVM_LINK_COMPONENTS ${${target}_OLD_LLVM_LINK_COMPONENTS})
 
   set(${project}_TABLEGEN "${target}" CACHE

Modified: llvm/trunk/tools/llvm-go/llvm-go.go
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-go/llvm-go.go?rev=246527&r1=246526&r2=246527&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-go/llvm-go.go (original)
+++ llvm/trunk/tools/llvm-go/llvm-go.go Mon Aug 31 22:14:31 2015
@@ -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,
 	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,
 		"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()
 	}

Modified: llvm/trunk/tools/llvm-shlib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-shlib/CMakeLists.txt?rev=246527&r1=246526&r2=246527&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-shlib/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-shlib/CMakeLists.txt Mon Aug 31 22:14:31 2015
@@ -2,11 +2,23 @@
 # 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.
 
+if(LLVM_LINK_LLVM_DYLIB)
+  if(DEFINED LLVM_DYLIB_COMPONENTS)
+    # To avoid inscrutable link errors, just disallow setting
+    # LLVM_DYLIB_COMPONENTS when we're intending to link tools
+    # and shared libraries with the dylib.
+    message(FATAL_ERROR "LLVM_DYLIB_COMPONENTS must not be set when LLVM_LINK_LLVM_DYLIB is ON")
+  endif()
+  if(NOT LLVM_DYLIB_EXPORT_ALL)
+    message(FATAL_ERROR "LLVM_DYLIB_EXPORT_ALL must be ON when LLVM_LINK_LLVM_DYLIB is ON")
+  endif()
+  set(LLVM_DYLIB_COMPONENTS all)
+endif()
 
-# 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 LLVM_LINK_LLVM_DYLIB is not OFF, 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
     ${LLVM_TARGETS_TO_BUILD}
@@ -45,6 +57,25 @@ set(SOURCES
 
 llvm_map_components_to_libnames(LIB_NAMES ${LLVM_DYLIB_COMPONENTS})
 
+if(LLVM_LINK_LLVM_DYLIB)
+  # 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 )
@@ -94,7 +125,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"




More information about the llvm-commits mailing list